题目大意

给定一个模板串, 再给出\(n\)个询问, 询问每一个串的循环串总共在原串中出现了多少次.

循环串: 比如说有\(str[] = \{ABCD\}\), 则其循环串有\(\{ABCD\}, \{BCDA\}, \{CDAB\}, \{DABC\}\), 共\(len\)个.

题解

把每一个串复制一遍放在原串后面: \(\{ABCD\} \to \{ABCDABC\}\), 放入原串的后缀自动机中匹配. 在匹配时, 假如下一位无法匹配, 则跳suffix link; 假如即使跳了suffix link, 最大长度\(len(suffix)\)仍然大于等于原串长度, 则也跳suffix link(相当于砍掉多余的部分).

放入SAM前要先跑一次KMP去循环节.

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <vector>
  4. const int LEN = (int)1e6;
  5. struct suffixAutomaton
  6. {
  7. struct state
  8. {
  9. state *suc[26], *pre;
  10. int len;
  11. int sz, tg;
  12. std::vector<state*> bck;
  13. inline state()
  14. {
  15. for(int i = 0; i < 26; ++ i)
  16. suc[i] = NULL;
  17. pre = NULL;
  18. sz = 1;
  19. bck.clear();
  20. tg = 0;
  21. }
  22. };
  23. state *rt, *lst;
  24. inline void insert(int c)
  25. {
  26. state *u = new state;
  27. u->len = lst->len + 1;
  28. for(; lst != NULL && lst->suc[c] == NULL; lst->suc[c] = u, lst = lst->pre);
  29. if(lst == NULL)
  30. u->pre = rt;
  31. else
  32. {
  33. state *p = lst->suc[c];
  34. if(p->len == lst->len + 1)
  35. u->pre = p;
  36. else
  37. {
  38. state *q = new state;
  39. *q = *p;
  40. q->len = lst->len + 1, q->sz = 0;
  41. p->pre = u->pre = q;
  42. for(; lst != NULL && lst->suc[c] == p; lst->suc[c] = q, lst = lst->pre);
  43. }
  44. }
  45. lst = u;
  46. }
  47. void DFS(state *u)
  48. {
  49. u->tg = 1;
  50. if(u->pre != NULL)
  51. u->pre->bck.push_back(u);
  52. for(int i = 0; i < 26; ++ i)
  53. if(u->suc[i] != NULL && ! u->suc[i]->tg)
  54. DFS(u->suc[i]);
  55. }
  56. void get(state *u)
  57. {
  58. for(std::vector<state*>::iterator p = u->bck.begin(); p != u->bck.end(); ++ p)
  59. get(*p), u->sz += (*p)->sz;
  60. }
  61. inline void build(char *str, int len)
  62. {
  63. lst = rt = new state;
  64. rt->len = 0;
  65. for(int i = 0; i < len; ++ i)
  66. insert(str[i] - 'a');
  67. DFS(rt);
  68. get(rt);
  69. }
  70. inline int match(char *str, int len, int cir)
  71. {
  72. state *u = rt;
  73. int cur = 0;
  74. long long ans = 0;
  75. for(int i = 0; i < len + cir - 1; ++ i)
  76. {
  77. for(; u != rt && u->suc[str[i] - 'a'] == NULL; cur = u->pre->len, u = u->pre);
  78. if(u->suc[str[i] - 'a'] != NULL)
  79. u = u->suc[str[i] - 'a'], ++ cur;
  80. for(; u != rt && u->pre->len >= len; cur = u->pre->len, u = u->pre);
  81. if(cur >= len)
  82. ans += u->sz;
  83. }
  84. return ans;
  85. }
  86. }SAM;
  87. int main()
  88. {
  89. #ifndef ONLINE_JUDGE
  90. freopen("CF235C.in", "r", stdin);
  91. #endif
  92. static char str[LEN];
  93. scanf("%s", str);
  94. int len = strlen(str);
  95. SAM.build(str, len);
  96. int n;
  97. scanf("%d\n", &n);
  98. for(int i = 0; i < n; ++ i)
  99. {
  100. static char str[LEN << 1];
  101. scanf("%s", str);
  102. int len = strlen(str);
  103. static int nxt[LEN];
  104. nxt[0] = -1;
  105. int p = nxt[0];
  106. for(int i = 1; i < len; ++ i)
  107. {
  108. for(; ~ p && str[i] ^ str[p + 1]; p = nxt[p]);
  109. nxt[i] = str[i] == str[p + 1] ? ++ p : p;
  110. }
  111. int cir = len % (len - nxt[len - 1] - 1) == 0 ? len - nxt[len - 1] - 1 : len;
  112. for(int i = 0; i < cir; ++ i)
  113. str[i + len] = str[i];
  114. printf("%d\n", SAM.match(str, len, cir));
  115. }
  116. }

Codeforces 235 C的更多相关文章

  1. [codeforces 235]A. LCM Challenge

    [codeforces 235]A. LCM Challenge 试题描述 Some days ago, I learned the concept of LCM (least common mult ...

  2. codeforces 235 div2 C Team

    题目:http://codeforces.com/contest/401/problem/C 题意:n个0,m个1,求没有00或111的情况. 这么简单的题..... 做题的时候脑残了...,今天,贴 ...

  3. codeforces 235 B. Let's Play Osu!

    You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. F ...

  4. codeforces 235 div2 B. Sereja and Contests

    Sereja is a coder and he likes to take part in Codesorfes rounds. However, Uzhland doesn't have good ...

  5. codeforces 235 div2 A. Vanya and Cards

    Vanya loves playing. He even has a special set of cards to play with. Each card has a single integer ...

  6. Codeforces 235 E Number Challenge

    Discription Let's denote d(n) as the number of divisors of a positive integer n. You are given three ...

  7. codeforces 235 B lets play osu!

    cf235B 一道有意思的题.(据说是美少女(伪)计算机科学家出的,hh) 根据题目要求,就是求ni^2的和. 而n^2=n*(n-1)+n; n*(n-1)=C(n,2)*2: 所以∑ai^2=∑a ...

  8. [ BZOJ 4318 & 3450 / CodeForces 235 B ] OSU!

    \(\\\) \(Description\) 一共进行\(N\)次操作,生成一个长度为\(N\)的\(01\)序列,成功对应\(1\),失败对应\(0\),已知每一次操作的成功率\(p_i\). 在这 ...

  9. Codeforces Round #235 (Div. 2) D. Roman and Numbers 状压dp+数位dp

    题目链接: http://codeforces.com/problemset/problem/401/D D. Roman and Numbers time limit per test4 secon ...

随机推荐

  1. pandas-Notes1

    #coding = utf-8 import pandas as pd import numpy as np import matplotlib as plt # series, like vecto ...

  2. VSCode编译C/C++(一)MinGW安装配置指南

    为什么不用IDE? 更加专业.轻便.其过程对于理解计算机也有更多的帮助 安装过程: 首先进入http://mingw.org/  ,点击右侧最新发布,可以下载,然后安装 点击桌面MinGWInstal ...

  3. windows下创建子进程过程中代码重复执行问题

    windows在启动子进程的时候会将主进程文件倒入到子进程中.导入模块就相当于执行这个模块中的代码, 所以第一个print会在主进程中执行一次,又在被导入的过程中在子进程中又执行了一次. p.star ...

  4. 如何打造一个"逼格"的web前端项目

    最近利用空余的时间(坐公交车看教程视频),重新了解了前后端分离,前端工程化等概念学习,思考如何打造一个“逼格”的web前端项目. 前端准备篇 前端代码规范:制定前端开发代码规范文档. PS:重中之中, ...

  5. Selenium WebDriver-通过键盘事件操作浏览器

    #encoding=utf-8 import unittest import time import chardet from selenium import webdriver class Visi ...

  6. Selenium WebDriver-操作单选框

    先判断按钮是否已经被选中 如果没有被选中,才可以点击 #encoding=utf-8 import unittest import time import chardet from selenium ...

  7. python 学习分享-文件操作篇

    文件操作 f_open=open('*.txt','r')#以只读的方式(r)打开*.txt文件(需要与py文件在同一目录下,如果不同目录,需写全路径) f_open.close()#关闭文件 打开文 ...

  8. day01_13.数组

    数组基本语法 <?php $a = array(键1=>值1,键2=>值2); ?> <?php $arr = array(1=>'张三的裤子',2=>'李四 ...

  9. Struts2报错:No result defined for action xxx and result input

    case如下: 1. 后台程序要升级, 修改了一些功能,但是没有修改或者添加action的参数. 2. 数据库需要升级,执行了一些sql,修改过action的值. 3. 当修改某个已经存在的记录,然后 ...

  10. [python篇][1]configparser 问题汇总

    https://wiki.python.org/moin/ConfigParserExamples 1 错误一 nicodeEncodeError: 'ascii' codec can't encod ...