问题:很经典,也很难,理解了一个下午。。。终于把KMP算法思想弄明白了。改天继续看看。
昨天写的,今天继续补充,KMP算法是由三个人发明的,KMP就是三个人名字的首字母。
下面开始讲这个经典的算法:
1、刚开始比较时,如果相等,下移;
2、继续比较,遇到不相等的,假设位置为j,然后找j之前最大长度相等的前缀和后缀。这个怎么找不好理解,但理解了就很简单。
用子串(现在作为主串)的第一个字符和j位置之前的第一个字符比较,如果相等,继续比较,第二个字符和j之前的第二个字符往后比较,。。。记录最大长度相等的前缀和后缀。
3、如果没有,则主串和子串都增1。
next数组的求法:
首先,初始化。next[0]=-1;next[1]=0;
其次,按照上面2的方法求next[j];其中j指的是子串中出现不匹配的情况,而next[j]本身指的是下次主串要与子串匹配的字符。
最后,当j等于子串长度时,匹配成功。
i-j就是匹配的起始位置,i是主串中最后匹配的位置。
代码:
#include <iostream>
#include <cstring>
using namespace std;
void getNext(char *s,int *next)
{
int k=-1,i=0;
next[0]=-1;
while(i<strlen(s)-1)
{
if(k==-1||s[i]==s[k])
{
k++;
i++;
next[i]=k;
}
else
{
k=next[k];
}
}
}
int KMPMatch(char *s,char *str)
{
int next[100];
int i=0,j=0;
getNext(str,next);
while(i<strlen(s))
{
if(j==-1||s[i]==str[j])
{
i++;
j++;
}
else
{
j=next[j];
}
if(j==strlen(str))
return i-strlen(str);
}
return -1;
}
int main()
{
char *s="abcebabcdecada";
char *str="abcd";
int n;
n=KMPMatch(s,str);
if(n==-1)
cout<<"未找到匹配字符串"<<endl;
else
cout<<"匹配的起始位置为:"<<n<<endl;
return 0;
}
运行结果:
