kmp算法 字符串模式匹配
目录
串的模式匹配
最朴素的思想,暴力搜索,遍历比较每一个元素,以此判断是否相等
但是,这种太慢!!!
为此,引入kmp算法的概念,理解难度不高,多实操,应该能会
用处:
1. 普通的双字符串匹配问题
朴素的先求解nxt数组,在进行kmp匹配
模板题 洛谷P3375
#include<iostream> #include<string> using namespace std; const int maxm=1e6+5; string s,t; int nxt[maxm]; void get_nxt(string a){ nxt[0]=-1; int j=0,k=-1,len=a.size(); while(j<len-1){ if(k==-1||a[j]==a[k]){ ++j;++k; nxt[j]=k;//此处没有用优化,因为题目要求输出最长前缀后缀 }else k=nxt[k]; } return ; } signed main(){ cin>>s>>t; get_nxt(t+".");//我学的这个nxt数组没有包含最后一位的最长前缀后缀,得自己小加一下,突然想想,发现这个好妙啊 int i=0,j=0,lens=s.size(),lent=t.size(); while(i<lens){ if(j==-1||s[i]==t[j]){ ++j;++i; }else j=nxt[j]; if(j==lent){ cout<<i-lent+1<<'\n'; j=0; i=i-(lent-1); } } for(int i=0;i<lent;++i){ cout<<nxt[i+1]<<" \n"[i==lent-1]; } return 0; }
模板题 CF625B B. War of the Corporations
#include<iostream> #include<string> using namespace std; const int maxm=30+5; int nxt[maxm]; string s,t; void get_nxt(string a){ nxt[0]=-1; int k=-1,j=0,len=a.size(); while(j<len-1){ if(k==-1||a[k]==a[j]){ ++j;++k; if(a[j]!=a[k]){//此处进行了优化 nxt[j]=k; }else{ nxt[j]=nxt[k]; } }else k=nxt[k]; } return ; } signed main(){ cin>>s>>t; get_nxt(t); int i=0,j=0,lens=s.size(),lent=t.size(),ans=0; while(i<s.size()){ if(j==-1||s[i]==t[j]){ ++i;++j; }else{ j=nxt[j]; } if(j==lent){ ++ans; j=0;//因为题意为替换,所以j=0重新开始判断 } } cout<<ans<<'\n'; return 0; } /* 上为id:199949442的代码 题为: https://codeforces.com/contest/625/problem/B 此题为统计出现次数,所以最后的部分不是直接推出而是继续匹配 k=-1意味着当前位无需判断,继续匹配下一位即可 下为id:199943666的提交的代码 void get_nxt() { int j=0,k=-1,len=strlen(a); nxt[0]=-1; while(j<len-1) { if(k==-1||a[j]==a[k]) { ++k;++j; nxt[j]=k;//此处存在赘余?得看题目 } else k=nxt[k]; } } int i=0,j=0; while(i<lenb) { if(j==-1||b[i]==a[j]) { ++i;++j; } else { j=nxt[j]; } if(j==lena) { j=0; cs++; } } */
相关资料:
- https://www.cnblogs.com/zzuuoo666/p/9028287.html#6. 参考文献 (个人推荐,所学来源)
https://blog.csdn.net/v_july_v/article/details/7041827#t10 (同样的文章,这个链接有些图片显示完全一点) - https://www.cnblogs.com/yjiyjige/p/3263858.html
注:
资料1注意几点:
最大长度表和nxt数组的关系——不难发现,next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。
利用了nxt的优化则丢失了最大长度表!!!
2. 循环节问题
若某个字符串是由某个子串循环构成的,那么就称该子串为原串的循环节,长度最短的循环节就是最短循环节,姑且将该字符串称之为循环字符串
想想nxt数组的意义:nxt[i] 就是第 i 位之前的字符串的前缀后缀相同的最大长度是多少
- 如果一个字符串是循环字符串,那么它的最短循环节长度为
,循环周期就是
相关证明 - 如果一个字符串不是循环字符串,想求解需要添加多少字符可以将其构成循环字符串,则添加的字符数为
当nxt[n]!=0时,(循环节长度-nxt[n]%循环节长度)%循环节长度;当nxt[n]==0时,为n
,循环节长度即为
(这一段的描述还有待商讨)
求最短循环字串 洛谷P4391
详见题解合集和提交代码
关键:发现
求补最少字符构成循环 Cyclic Nacklace
题意:
给你一个字符串,你仅可以在字符串的头部和尾部添加字符,将这个字符串首尾相连,问你添加字符的最少数,使得添加后的字符串是一个循环字符串
思路:
传送门
//>>>Qiansui #include<map> #include<set> #include<list> #include<stack> #include<cmath> #include<queue> #include<deque> #include<cstdio> #include<string> #include<vector> #include<utility> #include<iomanip> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<functional> #define ll long long #define ull unsigned long long #define mem(x,y) memset(x,y,sizeof(x)) #define debug(x) cout << #x << " = " << x << endl #define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl //#define int long long inline ll read() { ll x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48;ch=getchar();} return x*f; } using namespace std; typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<ull,ull> pull; typedef pair<double,double> pdd; /* 找循环节 */ const int maxm=1e5+5,inf=0x3f3f3f3f,mod=998244353; string ss; int nxt[maxm]; void get_nxt(string a){ nxt[0]=-1; int j=0,k=-1; while(j<a.size()){ if(k==-1||a[j]==a[k]){ ++j;++k; nxt[j]=k; }else k=nxt[k]; } return ; } void solve(){ cin>>ss; get_nxt(ss); int n=ss.size(); int l=n-nxt[n]; if(nxt[n]==0) cout<<n<<'\n';//特判 else cout<<(l-n%l)%l<<'\n'; return ; } signed main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int _=1; cin>>_; while(_--){ solve(); } return 0; }
相关资料:
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17277340.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程