打卡信奥刷题(2719)用C++实现信奥题 P3375 【模板】KMP
题目要求实现KMP算法,解决字符串匹配问题并计算模式串各前缀的最长border长度。输入两个字符串s1和s2,输出s2在s1中的所有匹配位置(从小到大),以及s2各前缀的最长border长度。示例中,输入"ABABABC"和"ABA",输出匹配位置1和3,以及border长度0 0 1。C++代码通过预处理模式串的kmp数组实现高效匹配,时间复杂度为O(n+
P3375 【模板】KMP
题目描述
给出两个字符串 s1s_1s1 和 s2s_2s2,若 s1s_1s1 的区间 [l,r][l, r][l,r] 子串与 s2s_2s2 完全相同,则称 s2s_2s2 在 s1s_1s1 中出现了,其出现位置为 lll。
现在请你求出 s2s_2s2 在 s1s_1s1 中所有出现的位置。
定义一个字符串 sss 的 border 为 sss 的一个非 sss 本身的子串 ttt,满足 ttt 既是 sss 的前缀,又是 sss 的后缀。
对于 s2s_2s2,你还需要求出对于其每个前缀 s′s's′ 的最长 border t′t't′ 的长度。
输入格式
第一行为一个字符串,即为 s1s_1s1。
第二行为一个字符串,即为 s2s_2s2。
输出格式
首先输出若干行,每行一个整数,按从小到大的顺序输出 s2s_2s2 在 s1s_1s1 中出现的位置。
最后一行输出 ∣s2∣|s_2|∣s2∣ 个整数,第 iii 个整数表示 s2s_2s2 的长度为 iii 的前缀的最长 border 长度。
输入输出样例 #1
输入 #1
ABABABC
ABA
输出 #1
1
3
0 0 1
说明/提示
样例 1 解释
。
对于 s2s_2s2 长度为 333 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 111。
数据规模与约定
本题采用多测试点捆绑测试,共有 4 个子任务。
- Subtask 0(30 points):∣s1∣≤15|s_1| \leq 15∣s1∣≤15,∣s2∣≤5|s_2| \leq 5∣s2∣≤5。
- Subtask 1(40 points):∣s1∣≤104|s_1| \leq 10^4∣s1∣≤104,∣s2∣≤102|s_2| \leq 10^2∣s2∣≤102。
- Subtask 2(30 points):无特殊约定。
- Subtask 3(0 points):Hack。
对于全部的测试点,保证 1≤∣s1∣,∣s2∣≤1061 \leq |s_1|,|s_2| \leq 10^61≤∣s1∣,∣s2∣≤106,s1,s2s_1, s_2s1,s2 中均只含大写英文字母。
C++实现
#include<iostream>
#include<cstring>
#define MAXN 1000010
using namespace std;
int kmp[MAXN];
int la,lb,j;
char a[MAXN],b[MAXN];
int main()
{
cin>>a+1;
cin>>b+1;
la=strlen(a+1);
lb=strlen(b+1);
for (int i=2;i<=lb;i++)
{
while(j&&b[i]!=b[j+1])
j=kmp[j];
if(b[j+1]==b[i])j++;
kmp[i]=j;
}
j=0;
for(int i=1;i<=la;i++)
{
while(j>0&&b[j+1]!=a[i])
j=kmp[j];
if (b[j+1]==a[i])
j++;
if (j==lb) {cout<<i-lb+1<<endl;j=kmp[j];}
}
for (int i=1;i<=lb;i++)
cout<<kmp[i]<<" ";
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐


所有评论(0)