查找字符串匹配的算法
1.next[i]数组,这里是对匹配串设置的一个数组,作用是能快速移动到不必重复移动的位置,意思是下标为i的字符前面(不包括i)的字符串中最大前缀和后缀重复的个数。首先要初始化一个next[0],因为0前面没有数,所以我们假设next[0]=-1,(-1就相当于无意义吧!)
下面就是next数组的核心代码:
void getnext(string s)
{
int j=0,k=-1;
next[0]=-1;
while(j<s.size()) //这个才是求的前面重复的最长距离
{ //cout<<j<<endl;
if(s[k]==s[j]||k==-1 )
next[++j]=++k;
else
k=next[k];
}
return;
}
我们可以看到当k=-1,j=0时很容易得到next[1]=0;表示下标为1的字符前面有0个重复的前后缀,当j>=1时就一直作比较。
这里一定要注意的是next[i]保存的是不包括i字符前字符串的最大重复的前后缀。这里的k=next[k]有一种递归的思想。
核心就是next的求法了,最后很简单的就得出了KMP算法
int KMP(string s,string t)
{
int i=0,j=0; //表示从原串和匹配串的头开始找
getnext(t);
while(i<s.length()&&j<t.length())
{
if(j==-1||s[i]==t[j])
{
j++;
i++;
}
else
j=next[j];
}
if(j>=t.length())
return (i-t.length()); //返回下标
else
return -1; //表示没有找到
}
正确代码
int KMP(string s,string t)
{
int i=0;
int j=0;
getnext(t);
int len2=t.size();
printf("slength:%d tlength:%d\n",s.length(),len2);
while(i<s.size()&&(j<len2)) //这里的陷阱
{
if(j==-1||s[i]==t[j])
{
++i;
++j;
}
else
j=next[j];
}
if(j>=t.length())
return (i-t.length());
else
return -1;
}
第一个代码是最开始的代码,但经过多次调试都只进行一次循环,最后发现了一个大坑,最开始我用j和string类型的t.size()比较,j是int类型的,可是t.size()返回的是unsigned类型的,比较的结果竟然是负数比正数还大,最后让一个int类型的len2=t.size()才得到正确的答案.在用比较运算符的时候,一定要注意前后数据类型是否一致!!!!