[关闭]
@AkamemakA 2022-07-13T11:56:10.000000Z 字数 1152 阅读 143

Atcoder 题解

Atcoder Beginner Contest 257 problem G 题解


题目链接:点我

题目大意

给定两个由小写字母构成的字符串

求一个最小的,使得字符串的k个前缀子串相连后等于字符串

如果不存在,则输出

样例输入1

  1. aba
  2. ababaab

样例输出1

  1. 3

样例解释1

字符串可以被看做,而的前缀子串。
字符串不能再被写作两个或以下的子串相连,因此输出

样例输入2

  1. atcoder
  2. ac

样例输出2

  1. -1

数据范围


解析

这到底需要用到算法(模式匹配法),这里不做详细介绍,有兴趣的可以去看其他人的详解博客。

简单来说,算法可以快速求出一个数组,表示一个字符串的前位中的最大前后缀匹配。如,对于字符串,则

对于本题,我们可以将字符串连接在一起,并且之间用一个字符串中不会出现的字符(如‘#’)来连接。使用计算出数组之后,就丢弃前个字符。并计算答案。

然后应该想到动态规划。定义表示取中前个字符所得的答案。

有了这个数组,我们便可以得到以下的递推公式:

代码实现

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=1e6+5;
  4. string s,t;
  5. int n,ne[N],f[N],ans=1;
  6. inline void kmp()
  7. {
  8. int j=-1;
  9. ne[0]=j;
  10. for(int i=1;i<s.size();i++){
  11. while(j>=0&&s[i]!=s[j+1])j=ne[j];
  12. if(s[i]==s[j+1]) j++;
  13. ne[i]=j;
  14. }//详解见其他
  15. }
  16. int main()
  17. {
  18. cin>>s>>t;
  19. n=s.size();//找到开始计算答案的地方
  20. s+='#';s+=t; //将两字符串连接起来,计算ne数组
  21. kmp(); //kmp算法
  22. for(int i=n+1;i<s.size();i++){
  23. if(ne[i]>=0) f[i]=f[i-ne[i]-1]+1;
  24. //如果ne[i]>=0,就代表可以从S中找到一个ne[i]这么长的子串前缀来串联
  25. //减1是减去'#'号所占的位置
  26. else f[i]=0x3f3f3f3f; //否则不可能拼凑出前i个字符
  27. }
  28. if(f[s.size()-1]>=N) cout<<-1;//如果写f[s.size()-1]==0x3f3f3f3f,会WA一个点(震怒)
  29. else cout<<f[s.size()-1];
  30. }

完结撒花~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注