题目大意:
  给你一个数字串s,一个序列范围l和r,(l和r的数字位数为d)求l到r中有多少个数,满足它的长度为d/2的子串,能够在s中被匹配。

思路:
  首先将s中每一个长度为d/2的子串插入后缀自动机。
  然后数位DP。
  f[i][j]中第一维表示当前树与l和r的关系,包含四个状态,用二进制表示,每一位对应与l和r的不同关系。
  第二维表示当前状态下每个结点匹配到的数的个数。
  每一个数位的状态由上一个数位转移而来,我们用两个DP数组f和g滚动实现。
  用o表示当前枚举的数字,用to表示数字所对应的第一维的状态,则转移方程为f[to[o]][p]=sum(f[j][par[p]])
  然而一开始写AC自动机用的是指针,然后又是各种不方便,所以又用vector很粗糙地实现了结点的遍历。故常数巨大。

  1. #pragma GCC optimize("O3")
  2. #include<queue>
  3. #include<cstdio>
  4. #include<vector>
  5. #include<cstring>
  6. const int mod=1e9+;
  7. const int N=,D=;
  8. char s[N],l[D],r[D];
  9. int n,d;
  10. class AhoCorasickAutomaton {
  11. private:
  12. static const int SIGMA_SIZE=;
  13. struct Node {
  14. Node *ch[SIGMA_SIZE],*fail;
  15. bool isEnd;
  16. int id;
  17. Node(const int i) {
  18. memset(ch,,sizeof ch);
  19. fail=NULL;
  20. isEnd=false;
  21. id=i;
  22. }
  23. };
  24. Node *root;
  25. std::vector<Node*> v;
  26. int idx(const char ch) {
  27. return ch-'';
  28. }
  29. int f[][N*D>>],g[][N*D>>];
  30. //第一维表示与l和r的关系
  31. public:
  32. AhoCorasickAutomaton() {
  33. root=new Node(v.size());
  34. v.push_back(root);
  35. }
  36. void insert(char s[],const int len) {
  37. Node *p=root;
  38. for(int i=;i<len;i++) {
  39. const int w=idx(s[i]);
  40. if(!p->ch[w]) {
  41. p->ch[w]=new Node(v.size());
  42. v.push_back(p->ch[w]);
  43. }
  44. p=p->ch[w];
  45. }
  46. p->isEnd=true;
  47. }
  48. void getFail() {
  49. std::queue<Node*> q;
  50. root->fail=root;
  51. for(int i=;i<SIGMA_SIZE;i++) {
  52. if(root->ch[i]) {
  53. root->ch[i]->fail=root;
  54. q.push(root->ch[i]);
  55. } else {
  56. root->ch[i]=root;
  57. }
  58. }
  59. while(!q.empty()) {
  60. Node *p=q.front();
  61. q.pop();
  62. for(int i=;i<SIGMA_SIZE;i++) {
  63. if(p->ch[i]) {
  64. p->ch[i]->fail=p->fail->ch[i];
  65. q.push(p->ch[i]);
  66. } else {
  67. p->ch[i]=p->fail->ch[i];
  68. }
  69. }
  70. }
  71. Node *end=new Node(v.size());
  72. for(unsigned i=;i<v.size();i++) {
  73. Node *p=v[i];
  74. for(int i=;i<SIGMA_SIZE;i++) {
  75. if(p->ch[i]->isEnd) {
  76. p->ch[i]=end;
  77. }
  78. }
  79. }
  80. for(int i=;i<SIGMA_SIZE;i++) {
  81. end->ch[i]=end;
  82. }
  83. v.push_back(end);
  84. }
  85. int dp() {
  86. g[][]=;
  87. int to[];
  88. for(int i=;i<d;i++) {
  89. for(int i=;i<;i++) {
  90. for(unsigned j=;j<v.size();j++) {
  91. f[i][j]=;
  92. }
  93. }
  94. for(int j=;j<;j++) {
  95. int st=(j&)?:idx(l[i]),en=(j>)?:idx(r[i]);//确定当前数位数字的上下界
  96. for(int i=st;i<=en;i++) to[i]=0b11;//默认是在l和r之间
  97. if(~j&) to[st]&=0b10;//如果比l小
  98. if(j<) to[en]&=0b01;//如果比r大
  99. //用&是因为有可能st=en
  100. for(unsigned k=;k<v.size();k++) {
  101. if(!g[j][k]) continue;
  102. for(int o=st;o<=en;o++) {//在当前数位的范围寻找子结点
  103. (f[to[o]][v[k]->ch[o]->id]+=g[j][k])%=mod;
  104. }
  105. }
  106. }
  107. std::swap(f,g);
  108. }
  109. int ret=;
  110. for(int i=;i<;i++) {
  111. ret=(ret+g[i][v.size()-])%mod;
  112. }
  113. return ret;
  114. }
  115. };
  116. AhoCorasickAutomaton acam;
  117. int main() {
  118. scanf("%s%s%s",s,l,r);
  119. n=strlen(s),d=strlen(l);
  120. for(int i=;i<=n-d/;i++) {
  121. acam.insert(&s[i],d/);
  122. }
  123. acam.getFail();
  124. printf("%d\n",acam.dp());
  125. return ;
  126. }

[CodeForces-585F]Digits of Number Pi的更多相关文章

  1. CF585F Digits of Number Pi

    题目 把\(s\)串所有长度为\(\lfloor \frac{d}{2}\rfloor\)的子串插入一个ACAM中,之后数位dp就好了,状态是\(dp_{i,j,0/1}\)第\(i\)位,在ACAM ...

  2. 题解 CF585F 【Digits of Number Pi】

    考虑用数位 \(DP\) 来统计数字串个数,用 \(SAM\) 来实现子串的匹配. 设状态 \(f(pos,cur,lenth,lim,flag)\),表示数位的位数,在 \(SAM\) 上的节点,匹 ...

  3. codeforces 464C. Substitutes in Number

    题目链接 C. Substitutes in Number time limit per test 1 second memory limit per test 256 megabytes input ...

  4. 【codeforces 805D】Minimum number of steps

    [题目链接]:http://codeforces.com/contest/805/problem/D [题意] 给你一个字符串; 里面只包括a和b; 让你把里面的"ab"子串全都去 ...

  5. Codeforces C. Split a Number(贪心大数运算)

    题目描述: time limit per test 2 seconds memory limit per test 512 megabytes input standard input output ...

  6. dp --- Codeforces 245H :Queries for Number of Palindromes

    Queries for Number of Palindromes Problem's Link:   http://codeforces.com/problemset/problem/245/H M ...

  7. Codeforces 279D The Minimum Number of Variables 状压dp

    The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...

  8. Educational Codeforces Round 11 D. Number of Parallelograms 暴力

    D. Number of Parallelograms 题目连接: http://www.codeforces.com/contest/660/problem/D Description You ar ...

  9. Codeforces 980 E. The Number Games

    \(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...

随机推荐

  1. linux中set、unset、export、env、declare,readonly的区别以及用法

    set命令显示当前shell的变量,包括当前用户的变量;   env命令显示当前用户的变量;   export命令显示当前导出成用户变量的shell变量.           每个shell有自己特有 ...

  2. Linux USB驱动学习总结(一)---- USB基本概念及驱动架构

    USB,Universal Serial Bus(通用串行总线),是一个外部总线标准,用于规范电脑与外部设备的连接和通讯.是应用在PC领域的接口技术.USB接口支持设备的即插即用和热插拔功能.USB是 ...

  3. Nginx常见错误与问题之解决方法技术指南

      Nginx常见错误与问题之解决方法技术指南. 安装环境: 系统环境:redhat enterprise 6.5 64bit 1.Nginx 常见启动错误 有的时候初次安装nginx的时候会报这样的 ...

  4. MySQL5.7之多源复制&Nginx中间件(上)【转】

    有生之年系列----MySQL5.7之多源复制&Nginx中间件(上)-wangwenan6-ITPUB博客http://blog.itpub.net/29510932/viewspace-1 ...

  5. 【Andorid开发框架学习】之Volley入门

    Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮.Volley特别适合数据量不大但是通信频繁的场景.在listView显示图片这方面,使用volley也是比较好的,不必 ...

  6. Jmeter 接口测试-请求 Headers 与传参方式

    1.添加信息表头. 注意:1.使用Parameters时,Content-Type要么不传,要么传application/x-www-form-urlencoded,因为不传时默认值就是applica ...

  7. Linux sudo 配置

    1.配置sudo权限 sudo配置信息保存在 /etc/sudoers 文件中,可以使用vi修改.但使用vi修改需要给root用户设置权限,可以使用 visudo 直接修改. visudo 复制这行将 ...

  8. [USACO18FEB]Snow Boots S

    提供一种无脑DP做法 题目中大概有这么些东西:位置,穿鞋,跑路 数据小,那么暴力开数组暴力DP吧 设dp[i][j]表示穿着鞋子j,到达位置i是否可行 无脑转移 枚举位置,正在穿哪双鞋,换成哪双走出去 ...

  9. R语言学习笔记:sort、rank、order、arrange排序函数

    R语言中排序有几个基本函数:sort().rank().order().arrange() 一.总结 sort()函数是对向量进行从小到大的排序 rank()函数返回的是对向量中每个数值对应的秩 or ...

  10. 题解-python-CodeForces 227A

    codeforces题目,用python写 本题输入三个点坐标,考察叉积,若大于0则right,小于0则left,等于0则towards 代码: a = raw_input().split() b = ...