题目3:文本文件单词的检索与计数(实现代码)

声明

BF的话主要是为了体现出KMP的高效之处,当然比BF更高效的还有BM,这里的话就不一一过多解释

BF算法

#include<iostream>
using namespace std;
//返回子串t在主串t中第pos个字符之后的位置;若不存在,函数返回0
//t非空,1≤pos≤s.size()
int Index(string s, string t, int pos=0)        //默认为0,默认从第一个元素开始查找
{
    
    
	int i = pos;				//主串t当前下表
	int j = 0;				//子串t当前下表
	while (i<s.size() && j<t.size())	//i小于s长度,j小于t长度,循环继续
	{
    
    
		if (s[i] == t[j])
		{
    
    
			i++;
			j++;
		}
		else				//指针退回,重新开始匹配
		{
    
    
			i = i - j + 1;	        //i退回到上一次匹配首位的下一位
			j = 0;			//j退回到子串t的首位
		}
	}
	if (j >= t.size())
		return i - t.size() + 1;	//i - t.size()表示从s[4]开始重复,+1表示该元素为第5个元素
	else
		return 0;
}
 
int main()
{
    
    
	string s = "goodgoogle";
	string t = "google";
	cout << Index(s, t)<<endl;
	return 0;
}

KMP算法

原版

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<Windows.h>
#define BUF_SIZE 256
typedef struct seqstring {
    
    
	char string[100];
	int length;
}seqstring;
 
void getnext(seqstring p, int next[]) {
    
    
	int i, j;
	i = 0;//指向字符串每个字符的下标
	j = -1;
	next[i] = j;//next[0]放上-1 
	while (i < p.length) {
    
    //没有到达结尾的话 
		if (j == -1 || p.string[i] == p.string[j]) {
    
    //如果是第一个字符或遇到相同的字符
			next[++i] = ++j;
		}
		else {
    
    
			j = next[j];
		}
	}
	for (i = 0;i < p.length;i++) {
    
    //输出next[]值 
		printf("%d ", next[i]);
	}
}
 
int kmp(seqstring t, seqstring p, int next[]) {
    
    
	int i, j;
	i = j = 0;
	while (i < t.length && j < p.length) {
    
    
		if (j == -1 || t.string[i] == p.string[j]) {
    
    
			i++;j++;
		}
		else {
    
    
			j = next[j];
		}
	}
	if (j == p.length) return i - p.length;
	else return -1;
}
int  main() {
    
    
	seqstring t, p;
	int next[50];
	
	
	DWORD	nIn;
    char buffer[BUF_SIZE] = "";
   HANDLE handle = CreateFile("test.txt",
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (handle == INVALID_HANDLE_VALUE) {
    
    
		printf("%d", GetLastError());
		return -1;
	}
	ReadFile(handle, buffer, BUF_SIZE, &nIn, NULL) ;
	

	strcpy(t.string, buffer);
	printf("%s\n", t.string);
	t.length = strlen(t.string);
 
	printf("please input string p:");
	scanf("%s", p.string);
	printf("%s\n", p.string);
	p.length = strlen(p.string);
	printf("next:");
	getnext(p, next);
	printf("\n%d\n", kmp(t, p, next));
}


在这里插入图片描述
在这里插入图片描述

改进版(符合题意版)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<Windows.h>
#include <iostream>
using namespace std;
#define BUF_SIZE 256
int counts = 0;
int direction[200] = {
    
    0};
typedef struct seqstring {
    
    
	char string[100];
	int length;
}seqstring;

void getnext(seqstring p, int next[]) {
    
    
	int i, j;
	i = 0;//指向字符串每个字符的下标
	j = -1;
	next[i] = j;//next[0]放上-1 
	while (i < p.length) {
    
    //没有到达结尾的话 
		if (j == -1 || p.string[i] == p.string[j]) {
    
    //如果是第一个字符或遇到相同的字符
			next[++i] = ++j;
		}
		else {
    
    
			j = next[j];
		}
	}
	for (i = 0; i < p.length; i++) {
    
    //输出next[]值 
		//printf("%d ", next[i]);
	}
}

int kmp(seqstring t, seqstring p, int next[]) {
    
    
	int i, j;
	i = j = 0;
	while (true) {
    
    
		if (j == -1 || t.string[i] == p.string[j]) {
    
    
			i++; j++;
		}
		else {
    
    
			j = next[j];
		}

		if (!(i < t.length && j < p.length)) {
    
    
			if (j == p.length) {
    
    
				direction[counts] = i - p.length;
				counts++;
				j = 0;
			}
			if (i == t.length) {
    
    
				return 0;
			}
		}

	}
	if (j == p.length) 
	{
    
     
		return i - p.length;
	}
	else
	{
    
    
		return -1;
	}
		
}
int  main() {
    
    
	seqstring t, p;
	int next[50];


	DWORD	nIn;
	char buffer[BUF_SIZE] = "";
	HANDLE handle = CreateFile("test.txt",
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (handle == INVALID_HANDLE_VALUE) {
    
    
		printf("%d", GetLastError());
		return -1;
	}
	ReadFile(handle, buffer, BUF_SIZE, &nIn, NULL);


	strcpy(t.string, buffer);
	printf("%s\n", t.string);
	t.length = strlen(t.string);

	printf("please input string p:");
	scanf("%s", p.string);
	printf("%s\n", p.string);
	p.length = strlen(p.string);
	//printf("next:");
	getnext(p, next);
	
	kmp(t, p, next);
	printf("\n%d\n", counts);
	printf("单词出现的位置如下:\n");
	for (int i = 0; i < counts; i++) {
    
    
		cout << direction[i]<<"  ";
	}
}


在这里插入图片描述

查找结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CSNN2019/article/details/114683626