当前位置:   article > 正文

[CF1038F]Wrap Around[AC自动机+dp]

cf1038f

题意

题目链接

分析

  • 题意容易转化成求循环之后不包含 s 的串的个数。

  • 首先建立 AC 自动机。考虑一个暴力的做法:枚举长度为 n字符串 t 最终(后缀) 和 s 的匹配长度是多少 (i)。

    这样在开始的时候,我们再记录一维从 t 的第 i+1 个位置开始匹配且没有匹配到 s 的方案数。

  • 最终状态: f(i,j,k,l) 表示 t 的后缀和 s 的匹配长度,考虑到了 t 的第 j 个字符,在 AC 自动机上从第一个位置出发到达的节点,在 AC 自动机上从第 i 个位置出发到达的节点。

  • 总时间复杂度为 O(n4)

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
  5. #define rep(i, a, b) for(int i = a; i <= b; ++i)
  6. #define pb push_back
  7. #define re(x) memset(x, 0, sizeof x)
  8. inline int gi() {
  9. int x = 0,f = 1;
  10. char ch = getchar();
  11. while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
  12. while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
  13. return x * f;
  14. }
  15. template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
  16. template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
  17. const int N = 44;
  18. int n, m;
  19. int ch[N][2], fail[N];
  20. LL f[N][N][N], ans;
  21. char s[N];
  22. int main() {
  23. n = gi();
  24. scanf("%s", s + 1);
  25. m = strlen(s + 1);
  26. rep(i, 1, m) ch[i - 1][s[i] - '0'] = i;
  27. rep(i, 1, m)
  28. rep(j, 0, 1)
  29. if(ch[i][j]) fail[ch[i][j]] = ch[fail[i]][j];
  30. else ch[i][j] = ch[fail[i]][j];
  31. ans = 1ll << n;
  32. rep(i, 0, m - 1) {
  33. memset(f, 0, sizeof f);
  34. f[0][0][i] = 1;
  35. rep(j, 0, n - 1)rep(k, 0, m - 1)rep(l, 0, m - 1)
  36. rep(c, 0, 1){
  37. int a = ch[k][c], b = ch[l][c];
  38. if(a == m || b == m) continue;
  39. f[j + 1][a][b] += f[j][k][l];
  40. }
  41. rep(j, 0, m - 1)
  42. ans -= f[n][i][j];
  43. }
  44. printf("%lld\n", ans);
  45. return 0;
  46. }

转载于:https://www.cnblogs.com/yqgAKIOI/p/10179654.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/1015903
推荐阅读
相关标签
  

闽ICP备14008679号