KMP算法
KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。
问题:求a字符串与b字符串中子串相同的串首位置。
暴力就不说了,设a长m,b长n,每次枚举比对每个字符,复杂度O(nm)。
KMP主要思想:如果一个字符串的子串与前缀相等,那么在查找时就可以直接将前缀跳至该子串的位置。复杂度O(n)。
nxt[x]记录x位置字符在查询串中的跳转位置。
eg:对于串abaabacac:
a b a a b a c a c
-1 0 0 1 1 2 3 0 1
inline void getnxt() { int j=0,k=-1; nxt[0]=-1; while(j<s.length()-1) { if(k==-1||s[j]==s[k])nxt[++j]=++k; else k=nxt[k]; } }
查询时跳转即可。
模拟一下就知道啦~
全代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; string s,t; int nxt[1000]; inline void getnxt() { int j=0,k=-1; nxt[0]=-1; while(j<s.length()-1) { if(k==-1||s[j]==s[k])nxt[++j]=++k; else k=nxt[k]; } } inline int indexkmp() { int i=0,j=0; while(i<s.length() and j<t.length())//如果比完了就退出来了 if(i==-1 or s[i]==t[j])i++,j++; else i=nxt[i]; if(i>=s.length())return j-s.length(); return -1; } int main() { std::ios::sync_with_stdio(false); cin>>s>>t; getnxt(); cout<<indexkmp()+1; return 0; }
例题
#include<iostream> #include<cstdio> #include<string> #include<cstring> using namespace std; const int maxn=1e6+5; int nxt[maxn]; char a[maxn],b[maxn]; int lena,lenb; inline void getnxt() { int k=-1,j=0; nxt[0]=-1; while(j<lena) if(k==-1 or a[k]==a[j]) nxt[++j]=++k; else k=nxt[k]; } inline void indexkmp() { int j=0,i=0; while(j<lena and i<lenb) if(j==-1 or a[j]==b[i]){ i++,j++; if(j==lena){ printf("%d\n",i-lena+1); j=nxt[j]; } } else j=nxt[j]; } int main() { scanf("%s\n%s",&b,&a); lena=strlen(a); lenb=strlen(b); getnxt(); indexkmp(); for(int i=1;i<=lena;i++) printf("%d ",nxt[i]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现