写在前面:
这些是我学习的时候的一些个人理解和笔记,如有错误,欢迎指正。
2.KMP
子串的定位运算通常称为串的模式匹配或是串匹配。著名的算法有BF算法和KMP算法。
2.1
- 这种算法是由Knuth、Morris和Pratt同时设计实现的,因此称为KMP算法。
- KMP算法是对BF算法的改进,在BF算法中,i和j指针都要进行回溯,但是在KMP算法中,i指针是不用回溯的,而是利用已经得到的“部分匹配”的结果将模式串T向右“滑动”尽可能远的一段距离之后继续进行比较。
- 最坏的情况:主串S:aaaaaaaaab 模式串T:aaab,找起来就会很慢
- BF算法的时间复杂度是 O(n*m),KMP算法时间复杂度是 O(n*m)
2.2求next[ j ]和nextval[ j ]的做题方法
- https://www.bilibili.com/video/BV1jY4y177Ci/?spm_id_from=333.999.0.0
next[ j ]:需要找到子串中最长的相同前后缀的长度。
nextval[ j ]:需要比较 下标为next[ j ]和当前的字符是否相等。
2.3代码
KMP算法
int Index_KMP(SString S,SString T,int pos)
{//T非空,i<=pos<=S.length
i=pos;j=1;
while(i<S.length && j<=T.length)
{
if(j==0||S.ch[i]==T.ch[j])
{
++i;++j;
}
else j=next[j];
if(j>T.length) return i-T.length;
else return 0;
}
}
计算next函数值
void get_next(SString T,int next[])
{
i=1; next[1]=0; j=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j]){++i;++j;next[i]=j;}
else j=next[j];
}
}
计算next函数修正值(nextval)
void get_nextval(SString T ,int nextval[])
{
i=1;nextval[1]=0;j=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
++i;++j;
if(T.ch[i]!=T.ch[j]) nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}