朴素算法
朴素算法中,P的第j位失配,默认的把P串后移一位
char s[]={' ','a','b','c','a','b','a','a','a','a','b','a','a','b','c','a','c'};//从序号1开始存
char p[]={' ','a','b','a','a','b','c','a','c'};
int i = 1,j = 1;
while(i<=sLen && j<=pLen){
if(s[i]==p[j]){i++;j++;}
else{
i = i-j+2;
j = 1;
}
}
朴素算法理解简单,但两个串都有依次遍历,时间复杂度为O(n*m)
相比朴素算法:
朴素算法: 每次失配,S串的索引i定位的本次尝试匹配的第一个字符的后一个。P串的索引j定位到1;T(n)=O(n*m)
KMP算法: 每次失配,S串的索引i不动,P串的索引j定位到某个数。T(n)=O(n+m),时间效率明显提高减少遍历的趟数
kmp算法
void Getnext(int next[],String t){
int j=0,k=-1;
next[0]=-1;
while(j<t.length-1)
{
if(k == -1 || t[j] == t[k]) next[++j] = ++k;
else k = next[k];//最难懂,一直倒推,直到相等或者j=0
}
}
改进
后面的B和C不匹配,k=next(3)=1 和t(1)比较
void Getnext(int next[],String t)
{
int j=0,k=-1;
next[0]=-1;
while(j<t.length-1)
{
if(k == -1 || t[j] == t[k])
{
j++;k++;
if(t[j]==t[k])//当两个字符相同时,就跳过
next[j] = next[k];
else
next[j] = k;
}
else k = next[k];
}
}
图解参考:https://blog.youkuaiyun.com/qq_37969433/article/details/82947411
但在前一轮的比较中,我们已经知道了P的前(j-1)位与S中间对应的某(j-1)个元素已经匹配成功了。找到了主串的部分内容可以让P多移几位,
代码
参考:https://blog.youkuaiyun.com/dark_cy/article/details/88698736
int KMP(String s,String t)
{
int next[MaxSize],i=0;j=0;
Getnext(t,next);
while(i<s.length&&j<t.length)
{
if(j==-1 || s[i]==t[j])
{
i++;
j++;
}
else j=next[j]; //j回退。。。
}
if(j>=t.length)
return (i-t.length); //匹配成功,返回子串的位置
else
return (-1); //没找到
}