【学习笔记】KMP
【学习笔记】KMP
因为字符串对我太抽象了,所以只能以水的心态写这个 KMP。
感觉考到字符串的题肯定要崩。
以下均规定字符串
前缀函数:
给定一个长度为
简单来说
周期:
若
border:
若
注意到存在 border
可以发现
进一步地
换句话说,利用
思路(求
-
对于
,有 。
实际上 当且仅当 。 -
对于
的情形,我们需要找到最大的 使得 且 。 -
可以不断地令
直至找到满足 且 的 。
附赠字符串下标从 1 开始的 KMP模板:(绝对不是因为从 0 开始写挂了)
注意如何比对两个字符串。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6+5;
int nxt[N];
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
string s1, s2; cin>>s1>>s2;
int len1 = s1.length(), len2 = s2.length();
s1 = ' '+s1, s2 = ' '+s2;
for(int i=2; i<=len2; i++){
nxt[i] = nxt[i-1];
while(nxt[i] && s2[nxt[i]+1]!=s2[i]) nxt[i] = nxt[nxt[i]];
if(s2[nxt[i]+1]==s2[i]) nxt[i]++;
}
for(int i=1, j=0; i<=len1; i++){
// j 是已经匹配完的模式串的最后一位的位置
while(j && s1[i]!=s2[j+1]) j=nxt[j];
if(s1[i]==s2[j+1]) j++;
if(j==len2){
cout<<i-len2+1<<"\n";
j = nxt[j]; // 继续匹配
}
}
for(int i=1; i<=len2; i++)
cout<<nxt[i]<<" ";
return 0;
}
因为我太菜了,所以 0 下标开始的只能附赠巨佬 @ysl_wf 的代码:
%%%%%%%%%%%%stO巨佬Orz%%%%%%%%%%%%%%
#include<bits/stdc++.h>
using namespace std;
typedef long long lt;
const lt N = 1e6 + 10;
lt pi[N];
lt la, lb, j;
char a[N], b[N];
int main(){
cin >> a;
cin >> b;
la = strlen(a), lb = strlen(b);
j = -1; pi[0] = -1;
for(int i = 1; i < lb; i++){
while(j >= 0 && b[i] != b[j+1])
j = pi[j];
if(b[j+1] == b[i])
j++;
pi[i] = j;
}
j = -1;
for(int i = 0; i < la; i++){
while(j >= 0 && b[j+1] != a[i])
j = pi[j];
if(b[j+1] == a[i])
j++;
if(j == lb-1){
printf("%lld\n", i-lb+2);
j = pi[j];
}
}
for(int i = 0; i < lb; i++){
printf("%lld ", pi[i]+1);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】