题目大意

给定字符串\(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

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int M=2000007; char s[M];
int n,m;
int last,tot;
int ch[M][26];
int stp[M],fa[M];
int right[M];
int pos[M],sum[M];
int vis[M],T; int newnode(int ss){
stp[++tot]=ss;
return tot;
} int ext(int p,int q,int d){
int nq=newnode(stp[p]+1);
fa[nq]=fa[q]; fa[q]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][d]==q;p=fa[p]) ch[p][d]=nq;
return nq;
} int sam(int p,int d){
int np=ch[p][d];
if(np) return (stp[p]+1==stp[np]) ? np : ext(p,np,d); np=newnode(stp[p]+1);
for(;p&&!ch[p][d];p=fa[p]) ch[p][d]=np;
if(!p) fa[np]=1;
else{
int q=ch[p][d];
fa[np]= (stp[p]+1==stp[q]) ? q : ext(p,q,d);
}
return np;
} void match(){
int p=1,len=0,i,d;
int res=0;
n=strlen(s+1);
for(i=1;i<=n;i++) s[i+n]=s[i];
for(i=1;i<=n*2;i++){
d=s[i]-'a';
if(!ch[p][d]){
for(;p&&!ch[p][d];p=fa[p]);
if(!p) p=1,len=0;
else{
len=stp[p]+1;
p=ch[p][d];
}
}
else{
len++;
p=ch[p][d];
} if(len>=n){
for(;n<=stp[fa[p]];p=fa[p]);
len=stp[p];
if(vis[p]!=T){
vis[p]=T;
res+=right[p];
}
}
}
printf("%d\n",res);
} int main(){ int i; scanf("%s",s+1);
n=strlen(s+1);
last=tot=1;
for(i=1;i<=n;i++){
last=sam(last,s[i]-'a');
right[last]=1;
}
for(i=1;i<=tot;i++) sum[stp[i]]++;
for(i=1;i<=tot;i++) sum[i]+=sum[i-1];
for(i=1;i<=tot;i++) pos[sum[stp[i]]--]=i;
for(i=tot;i>1;i--) right[fa[pos[i]]]+=right[pos[i]]; scanf("%d",&m);
while(m--){
scanf("%s",s+1);
T++;
match();
} return 0;
}

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. Oracle 事务 锁

    一. 事务 是一系列的数据库操作,是数据库应用的基本逻辑单位以及并发控制的基本单位.所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 要将有组语句作为事务考 ...

  2. jfinal excel表导出

    在自己的WEB项目中要用到导出Excel,所以结合网络上的资源写了一个自己的export 工具类. 说明: JFinal 环境 WEB项目 JAVA后台生成非JS插件 好了,直接撸代码 1.设置文件保 ...

  3. Cannot read property 'tap' of undefined

    E:\vue-project\vue-element-admin-master>npm run build:prod vue-element-admin@3.8.1 build:prod E:\ ...

  4. PAT 乙级 1024

    题目 题目地址:PAT 乙级 1024 题解 模拟题,重点需要考虑到各种不同情况:简单来说一下: 因为输入格式固定,所以把不同的部分分别存储和处理可以在很大程度上简化运算:其中需要考虑最多的就是小数部 ...

  5. 数据结构(C语言)分享笔记:数据结构的逻辑层次、存储层次

    [1] 严格意义上数据结构的概念 数据结构,一个简单的定义:相互之间存在一种或多种特定关系的数据元素的集合.即:数据结构 = 元素集合 + 元素间关系的集合 . 在讨论数据结构时,可以基于两个不同的层 ...

  6. linux主机状态检测方式

    之前写过一个简单的脚本检测当前网段中主机状态的脚本,内容如下: #! /bin/bash #ping check host status trap "exit" 2 sping() ...

  7. 七、Linux 文件与目录管理

    Linux 文件与目录管理 我们知道Linux的目录结构为树状结构,最顶级的目录为根目录 /. 其他目录通过挂载可以将它们添加到树中,通过解除挂载可以移除它们. 在开始本教程前我们需要先知道什么是绝对 ...

  8. JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列

    5456. [NOIP2017提高A组冲刺11.6]奇怪的队列 (File IO): input:queue.in output:queue.out Time Limits: 1000 ms  Mem ...

  9. I Like for You to Be Still【我会一直喜欢你】

    I Like for You to Be Still I like for you to be still 我会一直喜欢这你 It is as though you are absent 就算你并不在 ...

  10. Redis实现之压缩列表

    压缩列表 压缩列表(ziplist)是列表键和哈希键的底层实现之一,当一个列表键只包含少量列表项,并且每个列表项要嘛是整数值,要嘛是比较短的字符串,那么Redis就会使用压缩列表来做列表键的底层实现. ...