我看到的大神的从入门到深刻理解链接比我讲述的更为透彻
原文:https://blog.csdn.net/v_july_v/article/details/7041827
下面是我的对于kmp见解
kmp含义:
在我看来kmp说简单点就是求在母串中子串出现的位置;解题的关键就在于就求子串的相同的前缀和后缀用next数组存储在第i个字符(包含第i个字符)前有多少个相同的字符(下面讲述求法),另一个就是在kmp函数中找出那个位置的下标;
其实还有一种就是暴力求出下标的方法,暴力法求解由于对时间度要求很高所以,在题目要求子串,和母串长度很大时此方法明显就不适合了
AC如下 :
int Violentsearch(char* s, char* p)
{
int sLen = strlen(s);
int pLen = strlen(p);
int i = 0;
int j = 0;
while (i < sLen && j < pLen)
{
if (s[i] == p[j])
{
//如果当前字符匹配成功(即S[i] == P[j]),则i++,j++
i++;
j++;
}
else
{
//如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0
i = i - j + 1;
//如果失配,每一次都要从上一次母串最开始遍历的下一个字符开始重新遍历
//例如母串是aabcy子串是abcy遍历到第二个失配那么第二次就母串应该从第
//二个字符a开始重新遍历
j = 0;
}
}
//匹配成功,返回模式串p在文本串s中的位置,否则返回-1
if (j == pLen)
return i - j;
else
return -1;}
kmp数组next求法:
next数组的作用就是在kmp函数中子串和母串比较时不相等的话把子串前移到子串前面一部分和母串有相同的的地方例如
对于子串p:a b c d a b c y
对应的next数组应该是 0 0 0 0 1 2 3 0
初始化时数组全为零
定义一个i=1; j=0; j在a的位置,i在b的位置,不相等所以i++;j还不动,直到i在第五个字符a的时候出现第一个相等的此时i++;j++;next[i]=j;后面的同样相等直到遇到y的时候此时j在d上不相等所以j=next[j-1](j前面又没有相等的前缀和后缀)
建议使用第二种第一种容易出现错误
第一种:
void get_next()
{
int i = 1, j = 0;
while(i < lenb)
{
if(j == 0 && b[i] != b[j])
{
i ++;
next[i] = 0;
}
else if(j > 0 && b[i] != b[j])
j = next[j-1];
else
{
next[i] = j+1;
i ++;
j ++;
}
}
}
第二种
void Get_next()
{
int i=1,j=0;
next[0]=-1;
while(i<m)
{
if(j==-1||p[i]==p[j])
{
j++;
i++;
next[i]=j;//当前i的位置有j个相等的字符
}
else
{
j=next[j];//缩小前缀
}
}
}
对于kmp函数:
先看看代码吧
{
Get_next();
int i=0,j=0;
while(i<n)
{
//要是子串和母串相同继续往后进行比较
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else//不相等就把子串往后移到子串前面的几个字符和目前母串前几个相同的地方
//也就是上面的两张图片
{
j=next[j];
}
}
if(i==m)
return i-j;
else
return -1;
}