@AkamemakA
2022-07-13T11:56:10.000000Z
字数 1152
阅读 187
Atcoder 题解
题目链接:点我
给定两个由小写字母构成的字符串和。
求一个最小的,使得字符串的k个前缀子串相连后等于字符串。
如果不存在,则输出。
abaababaab
3
字符串可以被看做,而和是的前缀子串。
字符串不能再被写作两个或以下的子串相连,因此输出。
atcoderac
-1
这到底需要用到算法(模式匹配法),这里不做详细介绍,有兴趣的可以去看其他人的详解博客。
简单来说,算法可以快速求出一个数组,表示一个字符串的前位中的最大前后缀匹配。如,对于字符串,则。
对于本题,我们可以将字符串与连接在一起,并且之间用一个字符串中不会出现的字符(如‘#’)来连接。使用计算出数组之后,就丢弃前个字符。并计算答案。
然后应该想到动态规划。定义表示取中前个字符所得的答案。
有了这个数组,我们便可以得到以下的递推公式:
#include<bits/stdc++.h>using namespace std;const int N=1e6+5;string s,t;int n,ne[N],f[N],ans=1;inline void kmp(){int j=-1;ne[0]=j;for(int i=1;i<s.size();i++){while(j>=0&&s[i]!=s[j+1])j=ne[j];if(s[i]==s[j+1]) j++;ne[i]=j;}//详解见其他}int main(){cin>>s>>t;n=s.size();//找到开始计算答案的地方s+='#';s+=t; //将两字符串连接起来,计算ne数组kmp(); //kmp算法for(int i=n+1;i<s.size();i++){if(ne[i]>=0) f[i]=f[i-ne[i]-1]+1;//如果ne[i]>=0,就代表可以从S中找到一个ne[i]这么长的子串前缀来串联//减1是减去'#'号所占的位置else f[i]=0x3f3f3f3f; //否则不可能拼凑出前i个字符}if(f[s.size()-1]>=N) cout<<-1;//如果写f[s.size()-1]==0x3f3f3f3f,会WA一个点(震怒)else cout<<f[s.size()-1];}
完结撒花~