题目大意

给定字符串\(S\)与\(n<=10^5\)个串\(x_1,x_2...x_n\)(总长\(\le10^6\))

对于每个\(x_i\),输出有多少个\(S\)的子串与\(x_i\)循环流动

分析

对\(S\)建自动机

对于每个\(x\)将\(xx\)放进去匹配

暴力的做法是像\(LCS_2\)那样跑完后,按拓扑序遍历更新一次自动机

显然\(TLE\)

\(len\)为当前匹配长度

于是我们每匹配到一个\(len>=|x|\)就去算这个\(|x|\)长度子串出现次数

要往父亲跳直到\(min(p)<=|x|<=max(p)\)

跳完后不能回到原位置继续匹配,这样复杂度有问题

跳完后可以直接\(len=max(或|x|)\)不会影响答案

solution

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cctype>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. const int M=2000007;
  9. char s[M];
  10. int n,m;
  11. int last,tot;
  12. int ch[M][26];
  13. int stp[M],fa[M];
  14. int right[M];
  15. int pos[M],sum[M];
  16. int vis[M],T;
  17. int newnode(int ss){
  18. stp[++tot]=ss;
  19. return tot;
  20. }
  21. int ext(int p,int q,int d){
  22. int nq=newnode(stp[p]+1);
  23. fa[nq]=fa[q]; fa[q]=nq;
  24. memcpy(ch[nq],ch[q],sizeof(ch[q]));
  25. for(;p&&ch[p][d]==q;p=fa[p]) ch[p][d]=nq;
  26. return nq;
  27. }
  28. int sam(int p,int d){
  29. int np=ch[p][d];
  30. if(np) return (stp[p]+1==stp[np]) ? np : ext(p,np,d);
  31. np=newnode(stp[p]+1);
  32. for(;p&&!ch[p][d];p=fa[p]) ch[p][d]=np;
  33. if(!p) fa[np]=1;
  34. else{
  35. int q=ch[p][d];
  36. fa[np]= (stp[p]+1==stp[q]) ? q : ext(p,q,d);
  37. }
  38. return np;
  39. }
  40. void match(){
  41. int p=1,len=0,i,d;
  42. int res=0;
  43. n=strlen(s+1);
  44. for(i=1;i<=n;i++) s[i+n]=s[i];
  45. for(i=1;i<=n*2;i++){
  46. d=s[i]-'a';
  47. if(!ch[p][d]){
  48. for(;p&&!ch[p][d];p=fa[p]);
  49. if(!p) p=1,len=0;
  50. else{
  51. len=stp[p]+1;
  52. p=ch[p][d];
  53. }
  54. }
  55. else{
  56. len++;
  57. p=ch[p][d];
  58. }
  59. if(len>=n){
  60. for(;n<=stp[fa[p]];p=fa[p]);
  61. len=stp[p];
  62. if(vis[p]!=T){
  63. vis[p]=T;
  64. res+=right[p];
  65. }
  66. }
  67. }
  68. printf("%d\n",res);
  69. }
  70. int main(){
  71. int i;
  72. scanf("%s",s+1);
  73. n=strlen(s+1);
  74. last=tot=1;
  75. for(i=1;i<=n;i++){
  76. last=sam(last,s[i]-'a');
  77. right[last]=1;
  78. }
  79. for(i=1;i<=tot;i++) sum[stp[i]]++;
  80. for(i=1;i<=tot;i++) sum[i]+=sum[i-1];
  81. for(i=1;i<=tot;i++) pos[sum[stp[i]]--]=i;
  82. for(i=tot;i>1;i--) right[fa[pos[i]]]+=right[pos[i]];
  83. scanf("%d",&m);
  84. while(m--){
  85. scanf("%s",s+1);
  86. T++;
  87. match();
  88. }
  89. return 0;
  90. }

cf 235C 后缀自动机的更多相关文章

  1. Cyclical Quest CodeForces - 235C 后缀自动机

    题意: 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数, 圆环匹配的意思是将该子串拆成两段再首位交换相接的串和母串匹配,比 如aaab变成baaa,abaa,aaba再进行匹配. ...

  2. Codeforces 235C Cyclical Quest - 后缀自动机

    Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in ...

  3. CF 666E Forensic Examination——广义后缀自动机+线段树合并

    题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...

  4. CF 316G3 Good Substrings——广义后缀自动机

    题目:http://codeforces.com/contest/316/problem/G3 对询问串和模式串一起建一个后缀自动机,做出在每个串上的 right 集合大小之后枚举自动机上的每个点看看 ...

  5. 【CodeForces - 235C】Cyclical Quest 【后缀自动机】

    题意 给出一个字符串s1和q个询问,每个询问给出一个字符串s2,问这个询问的字符串的所有不同的周期串在s1中出现的次数的和. 分析 对于s1建后缀自动机.对于询问的每个字符串s2,我们按照处理循环串的 ...

  6. CF G. Indie Album 广义后缀自动机+树链剖分+线段树合并

    这里给出一个后缀自动机的做法. 假设每次询问 $t$ 在所有 $s$ 中的出现次数,那么这是非常简单的: 直接对 $s$ 构建后缀自动机,随便维护一下 $endpos$ 大小就可以. 然而,想求 $t ...

  7. CF 149E Martian Strings 后缀自动机

    这里给出来一个后缀自动机的题解. 考虑对 $s$ 的正串和反串分别建后缀自动机. 对于正串的每个节点维护 $endpos$ 的最小值. 对于反串的每个节点维护 $endpos$ 的最大值. 这两个东西 ...

  8. 后缀自动机(SAM)

    *在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...

  9. 【算法】后缀自动机(SAM) 例题

    算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...

随机推荐

  1. Linux下的GPT分区,使用parted命令

    Linux下的GPT分区,这是另外一种分区,针对MBR分区,它有很多优点: (1)几乎突破了分区个数的限制. 在GPT分区表中最多可以支持128个主分区. (2)单个分区容量几乎没有限制. 单个分区最 ...

  2. java抓取12306火车余票信息

    最近在弄一个微信的公众帐号,涉及到火车票查询,之前用的网上找到的一个接口,但只能查到火车时刻表,12306又没有提供专门的查票的接口.今天突然想起自己直接去12306上查询,抓取查询返回的数据包,这样 ...

  3. 选择 NoSQL 数据库需要考虑的 10 个问题

    那么我为什么要写这篇文章呢? 是因为我认为NoSQL解决方案不如RDBMS解决方案吗?当然不! 是因为我专注于SQL的做事方式,而不想陷入一种相对较新的技术的不确定性吗?不,也不是!事实上,我非常兴奋 ...

  4. 19.VUE学习之- v-for与computed结合功能 筛选实例讲解

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 数据结构-哈夫曼(Huffman)

    #include <iostream> #include <cstdio> #include <malloc.h> #define LIST_INIT_SIZE 1 ...

  6. B1066 图像过滤 (15分)

    B1066 图像过滤 (15分) 图像过滤是把图像中不重要的像素都染成背景色,使得重要部分被凸显出来.现给定一幅黑白图像,要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换. 输入格式 ...

  7. A1058 A+B in Hogwarts (20)(20 分)

    A1058 A+B in Hogwarts (20)(20 分) If you are a fan of Harry Potter, you would know the world of magic ...

  8. hive操作语句

    设置属性: //设置本地执行作set hive.exec.mode.local.auto=true; //设置动态分区 set hive.exec.dynamic.partition=true; se ...

  9. loj2063 「HAOI2016」字符合并

    ref #include <iostream> #include <cstring> #include <cstdio> using namespace std; ...

  10. laravel5.2总结--redis使用

    一切的前提都是已经安装好了redis服务器,并且能启动(我只总结了mac的安装方法:传送门) 我自己使用的是mac系统,有个教程可以参考下,传送门: 1.安装PHP PRedis 1>PRedi ...