随笔 - 164  文章 - 0  评论 - 4  阅读 - 9812

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++;
}
}
*/

相关资料:

  1. https://www.cnblogs.com/zzuuoo666/p/9028287.html#6. 参考文献 (个人推荐,所学来源)
    https://blog.csdn.net/v_july_v/article/details/7041827#t10 (同样的文章,这个链接有些图片显示完全一点)
  2. https://www.cnblogs.com/yjiyjige/p/3263858.html

注:
资料1注意几点:
最大长度表和nxt数组的关系——不难发现,next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。
利用了nxt的优化则丢失了最大长度表!!!

2. 循环节问题

若某个字符串是由某个子串循环构成的,那么就称该子串为原串的循环节,长度最短的循环节就是最短循环节,姑且将该字符串称之为循环字符串
想想nxt数组的意义:nxt[i] 就是第 i 位之前的字符串的前缀后缀相同的最大长度是多少

  • 如果一个字符串是循环字符串,那么它的最短循环节长度为nnxt[n],循环周期就是n/(nnxt[n])
    相关证明
  • 如果一个字符串不是循环字符串,想求解需要添加多少字符可以将其构成循环字符串,则添加的字符数为当nxt[n]!=0时,(循环节长度-nxt[n]%循环节长度)%循环节长度;当nxt[n]==0时,为n,循环节长度即为nnxt[n]
    (这一段的描述还有待商讨)

求最短循环字串 洛谷P4391

详见题解合集和提交代码
关键:发现ans=nlen

求补最少字符构成循环 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;
}

相关资料:

  1. 字符串最短循环节
  2. KMP算法中的循环节问题
posted on   Qiansui  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示