KMP学习笔记
KMP
KMP是一种非常有用的算法,可以将字符串匹配的复杂度由 降到
朴素算法
学过语言就会朴素算法,这里只给出伪代码:
for(i=0->n-1){ for(j=i>m-i){ if(s[i]!=s[j])goto fg; } cout<<i<<endl; fg:; }
时间复杂度 。
KMP
KMP是基于DP的一种字符串匹配算法。
他先扫一遍模式串,建立 next
数组。
再通过 next
数组自动判断可以文本串当前位置能匹配到模式串第几个。
这听起来很神奇,但做起来更神奇。
图解
建立失配指针
假设模式串为abcabc
我们令红色箭头为匹配后的推进,蓝色箭头为失配后的推进。
next[0]
只有a
才能推进,所以只有next[0]
如果相同则推进至 1
next[1]
只有b
才能推进,所以只有next[1]
如果相同则推进至 2
next[2]
同理,只有c
才能推进,所以只有next[2]
如果相同则推进至 3
next[3]
从这里开始推进就不讲了。
当a
失配时,我们看到它与前面的a
有相同的前缀,所以a
的失配指针为0
next[4]
当b
失配时,我们看到它与前面的ab
有相同的前缀,所以b
的失配指针为1
next[5]
当c
失配时,我们看到它与前面的abc
有相同的前缀,所以c
的失配指针为3
结果
结果如下图:
匹配
假设文本串为abcdababcabc
。
黑色为当前走的箭头。
abc
直接跳到了3
d
失配了,因为模式串中没有一个d
,所以直接跳到了0
ab
直接跳到了2
a
失配了,因为模式串中上第一个a
在1
,所以直接跳到了1
bcabc
直接跳到了5
,匹配成功!
代码
#include<bits/stdc++.h> using namespace std; #define int long long int nex[5000001]={0}; void KMP(string s){ int j=0; nex[0]=1; for(int i=2;i<s.size();i++){ while(j&&s[i]!=s[j+1])j=nex[j];//找上一个前缀相同的 if(s[j+1]==s[i])j++; nex[i]=j;//建立匹配指针 } } void goo(string s,string s2,int a){ int j=0; for(int i=1;i<s.size();i++){ while(j&&s[i]!=s2[j+1])j=nex[j];//运行失配指针 if(s[i]==s2[j+1])j++; if(j==a){//匹配完成 cout<<i-a+1<<endl;//输出 j=nex[j];//下一个 } } } signed main(){ string a1,a2; cin>>a1>>a2; a1=" "+a1; a2=" "+a2; KMP(a2); goo(a1,a2,a2.size()-1); for(int i=1;i<a2.size();i++)cout<<nex[i]<<" "; return 0; }
本文作者:ccrui
本文链接:https://www.cnblogs.com/ccr-note/p/KMP.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步