@AkamemakA
2022-07-13T11:56:10.000000Z
字数 1152
阅读 143
Atcoder
题解
题目链接:点我
给定两个由小写字母构成的字符串和。
求一个最小的,使得字符串的k个前缀子串相连后等于字符串。
如果不存在,则输出。
aba
ababaab
3
字符串可以被看做,而和是的前缀子串。
字符串不能再被写作两个或以下的子串相连,因此输出。
atcoder
ac
-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];
}
完结撒花~