代码展示:
#include<iostream>
#include<string>
using namespace std;
#define MAXSIZE 20
//命名String为大小是MAXSIZE的字符数组
typedef char String[MAXSIZE];
//创建一个其值等于s的串S
int StrAssign(String S, char* s)
{
//串中下标为0的空间储存串的长度
S[0] = strlen(s);
//判断字符串s能否储存到串S中
if (S[0] < MAXSIZE)
{
//能储存到串的情况
for (int i = 1; i <= S[0]; i++)
{
//将字符串s的值复制到串S中
S[i] = *s;
s++;
}
return 1;
}
else
//不能储存到串的情况
return 0;
}
//获得next数组函数
void Get_next(String T,int *next)
{
int i = 1;
int j = 0;
next[1] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
i++;
j++;
//KMP模式匹配算法的改进
//当前求得下标为i的next值,要是下标为i的字符与它的前一个字符(下标为j的字符)不相同就不需要优化
if (T[i] != T[j])
next[i] = j;
//下标为i的字符与它的前一个字符(下标为j的字符)相同就需要优化
//字符相同就可以简化下标为i的字符的next值,让下标为i的字符的next值与它的前一个字符的next值相同
else
next[i] = next[j];
}
else
{
//如果匹配不相同,则i不同,j回溯到相同下标next数组中所储存数据的位置
//在求next函数中有种递归的感觉,但其实可以联合KMP算法理解,求next数组和KMP算法过程差不多
j = next[j];
}
}
}
//KMP算法
//返回字串T在主串S中第pos个字符之后的位置,若不存在,则函数返回值为0
int Index_KMP(String S, String T, int pos)
{
int i = pos;
int j = 1;
//创建一个空int数组作为next数组
int next[50];
//调用Get_next函数得到next数组
Get_next(T, next);
while (i <= S[0] && j <= T[0])
{
//相等则向下继续遍历
//如果j为1时指向的字符就与i指向的字符不相当,那么j会回溯到j=0处的位置,此时就应该i和j都向前移
if (j==0||S[i] == T[j])
{
i++;
j++;
}
//不相等j回溯,回溯的值是next数组中相应下标储存的值
else
j = next[j];
}
//遍历完了子串,说明在主串中找到了符合条件的部分
if (j > T[0])
return i - T[0];
//没有在主串找到符合条件的下标
else
return 0;
}
int main()
{
//主字符串s
char s[] = "goodgoogle";
//子字符串t
char t[] = "google";
//创建串S和T
String S, T;
//创建串失败直接退出
if (StrAssign(S, s) == 0)
return 0;
if (StrAssign(T, t) == 0)
return 0;
int pos = 2;
cout << Index_KMP(S, T, pos);
system("pause");
return 0;
}
我肯定是说不清楚KMP算法的,只能说自己的感想
KMP模式匹配算法是图中的函数Get_next()和函数Index_KMP()。
KMP模式匹配算法很关键的一点就是算出子串的next数组,next数组代表当前字符之前的串的前后缀的相似度
KMP算法与朴素的模式匹配算法的区别就是,朴素的模式匹配算法是将主串的每一个元素都作为头元素与子串进行比较,在子串上遍历的指针每次都回到1处。KMP算法当发现主串和字串上的字符不相同时,在子串上遍历的指针会回溯到next数组相应位置储存的值处。(KMP算法在主串上遍历的指针是不需要回溯的,只需要在子串上遍历的指针回溯就行了,而朴素的模式匹配算法在主串上遍历的指针也是需要回溯的,所以KMP算法能够节省大量的时间)
KMP模式匹配算法的改进:
改进的是求next数组的函数
其实就是对于字串上有很多相同的字符连在一起时特殊情况,还能进行优化,如果子串中后一个字符和前一个字符相同,则后一个字符可以沿用前一个字符的next值,这样就能在使用KMP算法时对于有很多相同字符的子串减少很多回溯的次数。
书上说法:总结改进过的KMP算法,它是在计算出next值的同时,如果a位字符与它的next值指向的b位字符相等,则a位的next就指向b位的next值,如果不等,则a位的next值就是它自己的next值。