kmp能够实现单模板串的快速匹配。
备忘:cstring 头文件里的char* strstr 函数也是比较一个字符串是否为另一个字符串的子串,与KMP功能相同,速度究竟谁快?
经过测试,aaaaaa…….aaaab(len =1000) 去匹配 aaaaaaa…..aaab(len=1000000)
strstr 函数用了将近一秒钟,而kmp算法只花了不到0.1秒的时间。除了这种极端的情况外,其他一般情况strstr与kmp表现相当。
比赛中有时候可以用strstr水过。
kmp基本概念和原理略去,直接上next数组。
0 | 1 | 2 | 3 | 4 | 5 | |
str | a | b | c | a | b | |
next | -1 | 0 | 0 | 0 | 1 | 2 |
当匹配到s[i]失配时(也就是s[i]与文本串不匹配),i 跳到next[i-1]+1。
next(jump)数组构建过程正确性的归纳证明:
KMP算法中jump数组的构建可以通过归纳法来解决,首先确定jump[1]=0;假设jump[j]=k,
也就是P[0, k] == P[j-k, k],如果P[j+1] == P[k+1],那么得出[0,k+1] = P[j-k, j+1],从而
更加定义得出jump[j+1] = k+1;
如果P[j+1] != P[k+1],那就接着比较P[j+1] ?= P[k1+1],其中(jump[k] = k1),根据
(jump[k]=k1)的定义,P[0,k1] == P[k-k1, k],根据(jump[j]=k)的定义,P[0, k] ==
P[j-k, k],根据这两个等式,推出P[0, k1] == P[j-k1, j],如果此时P[j+1] == P[k1+1],则
得出:jump[j+1] = K1 +1 = jump[k] +1。
如果P[j+1] != P[K1+1],继续递归比较P[j+1] 和P[jump[jump[k]]+1] …. P[1];
如果依次比较都不相等,那么jump[j+1] = 0;写成代码如下,可以看出其实就是模式串自我
匹配的过程。
//生成jump(又叫next) 数组的函数,其中str下标从1开始,str[0] 为空,则jump[0] = -1 ,
void PrintJump(char *str){ //其中str下标从1开始,str[0] 为空,则jump[0] = -1 jump[0] = -1; jump[1] = 0; int len = strlen(str+1); int j=1,k; while(j<len){ //计算jump[j+1] k = jump[j]; //已知jump[j]==k while(k!=-1&&str[k+1]!=str[j+1]) k = jump[k]; jump[j+1] = k+1; j++; } }
//如果在s1中找到s2,返回真。同样地s2下标从1开始,s1下标从0开始。
bool Find(char *s1,char *s2){ int i=0,j=1; while(1){ if(j&&s2[j]=='