BF和KMP算法(附自己写的源码)

字符串子串查找

BF:爆破法

KMP:3个人总结的,所以是3个人的名字结合

BF爆破法,就是由两个指针一个一个进行比较,比较字符如果不是一样的,则主串指针退回到比较开始的下一个字符重新开始,子串指针回到字串第一位字符。

如图所示:

KMP算法,则是在BF的基础上进行的优化,即比较字符的时候,上面的指针不动,下面指针归0,然后再进行比较。

如图所示:

又考虑到可能有特殊情况,aaaab和aaab这种类似刁民的东西。

特殊情况:

所以引入了一个K值进行针对。

K的意义是,父串和子串前面有K个字符相等

假设上面是i,下面是j,下面比较的下标就是j+=(k-1)

所以就会如图所示:

所以要专门准备一个函数,求这些K,所以我们可以制造一个next数组

没有找到则返回-1.

如图,可以看到BF算法和KMP算法,然后中间的是KMP在进行的时候k的值:-1 0 1 2.

代码如下:

#include<stdio.h>
#include<string.h>
struct Str
{
public:
	char* pStr;
	int len;
public:
	Str() 
	{
		pStr = NULL;
		len = 0;
	}
	Str(const char* p)
	{
		len = strlen(p);
		pStr = new char[len + 1];
		memcpy(pStr, p, sizeof(char)*len);
		pStr[len] = 0;//结束符号
	}
	Str(const Str& s)//拷贝函数
	{
		len = s.len;
		if (0==len)
		{
			pStr = NULL;
		}
		else
		{
			pStr = new char[len + 1];
			memcpy(pStr, s.pStr, sizeof(char) * (len+1));
		}
	}
};

//找字串 找到返回下标,没找到返回-1
//BF(brute-force暴力破解)
int BF(char* pStr1, char* pStr2);
//创建偏移表的函数
void getNext(Str s, int* next);

//KMP算法
int KMP(Str s1,Str s2);
int main()
{
	Str s1("abcdaadaaaccdcd");
	Str s2("aaac");

	printf("BF: %d \n", BF(s1.pStr, s2.pStr));
	printf("KMP: %d \n", KMP(s1, s2));
	while (1)
	{

	}
	return 0;
}
int BF(char* pStr1, char* pStr2)
{
	int i = 0;//主串的
	int j = 0;//字串的
	int Idx = 0;//坐标
	while (1)
	{
		if ('\0'==pStr1[i] || '\0' == pStr2[j])
		{
			break;
		}
		if (pStr1[i] == pStr2[j])
		{
			i++;
			j++;
		}
		else
		{
			Idx++;
			i = Idx;
			j = 0;
		}
	}
	if ('\0' == pStr2[j])
	{
		return Idx;
	}
	return -1;
}
void getNext(Str s, int* next)
{
	char* pstr = s.pStr;
	int len = s.len;
	int j = 0; int k = -1;
	next[0] = k;//第一个元素k=-1,表示j不动,i动
	while (j<len)
	{
		if (k == -1 || pstr[j] == pstr[k])
		{
			//next[++j] = ++k;//next[j+1]=k+1
			if (pstr[++j]==pstr[++k])
			{
				next[j] = k;
			}
			else
			{
				next[j] = k;
			}
		}
		else
		{
			k = next[k];
		}
	}
}
int KMP(Str s1, Str s2)
{
	char* pStr1 = s1.pStr;
	char* pStr2 = s2.pStr;
	int* next = new int[s2.len];
	getNext(s2, next);
	for (int i = 0; i < s2.len; i++)
	{
		printf("%d", next[i]);
	}
	printf("\n");
	int i = 0;
	int j = 0;
	while (i<s1.len && j<s2.len)
	{
		if (-1==j ||pStr1[i]==pStr2[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	if (j==s2.len)
	{
		return (i - j);
	}
	return -1;
}

猜你喜欢

转载自blog.csdn.net/q244645787/article/details/128575376