【Codeforces235C】Cyclical Quest 后缀自动机
C. Cyclical Quest
standard output
Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in a string s" quickly by preprocessing the string s. But now he wants to make it harder.
So he wants to ask "how many consecutive substrings of s are cyclical isomorphic to a given string x". You are given string s and nstrings xi, for each string xi find, how many consecutive substrings of s are cyclical isomorphic to xi.
Two strings are called cyclical isomorphic if one can rotate one string to get the other one. 'Rotate' here means 'to take some consecutive chars (maybe none) from the beginning of a string and put them back at the end of the string in the same order'. For example, string "abcde" can be rotated to string "deabc". We can take characters "abc" from the beginning and put them at the end of "de".
Input
The first line contains a non-empty string s. The length of string s is not greater than 106 characters.
The second line contains an integer n (1 ≤ n ≤ 105) — the number of queries. Then n lines follow: the i-th line contains the string xi — the string for the i-th query. The total length of xi is less than or equal to 106 characters.
In this problem, strings only consist of lowercase English letters.
Output
For each query xi print a single integer that shows how many consecutive substrings of s are cyclical isomorphic to xi. Print the answers to the queries in the order they are given in the input.
Examples
baabaabaaa
5
a
ba
baa
aabaa
aaba
7
5
7
3
5
aabbaa
3
aa
aabb
abba
2
3
3
Solution
题目大意:给出一个字符串T,再给出N个字符串S,每次回答字符串S的所有循环串在T中出现次数,重复的不计入答案. 这里的循环串的意思 每次将首位字符置于末位置后形成的新串.
后缀自动机
先对模板串建后缀自动机,然后对于询问的每个串分别放到自动机上匹配,并统计答案.
具体的过程就是,对于询问的每个串S,构建成串SS,然后放到自动机上匹配,匹配的方法和求LCS时类似,如果匹配到的位置$>N$且匹配的长度$>=N$那么说明匹配出了一种循环串,这时候可以考虑统计这个循环串的答案.
就是在询问之前拓扑排序递推出每个节点的贡献,然后如果此时匹配到的点在Parent树中的节点刚好能够表示长度为N的子串,那么直接累加贡献即可,否则沿Parent指针跳到合适的节点再累加贡献即可.
这样累加贡献显然会出现重复的情况,那么只需要在每个节点上再打上一个标记,如果此次查询未利用这个节点的贡献,则计入贡献,否则跳过,即可得解.
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 1000010
char S[MAXN<<1];
int N,Q;
namespace SAM
{
int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1],size[MAXN<<1];
int last,sz=1,root=1;
inline void Init() {last=root;}
inline void Extend(int c)
{
int cur=++sz,p=last;
len[cur]=len[p]+1; size[cur]=1;
while (p && !son[p][c]) son[p][c]=cur,p=par[p];
if (!p) par[cur]=root;
else
{
int q=son[p][c];
if (len[p]+1==len[q]) par[cur]=q;
else
{
int nq=++sz;
memcpy(son[nq],son[q],sizeof(son[nq]));
len[nq]=len[p]+1;
par[nq]=par[q];
while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
par[cur]=par[q]=nq;
}
}
last=cur;
}
inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(S[i]-'a'+1);}
int st[MAXN],id[MAXN<<1];
inline void Pre()
{
for (int i=1; i<=sz; i++) st[len[i]]++;
for (int i=1; i<=N; i++) st[i]+=st[i-1];
for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
for (int i=sz; i>=1; i--)
size[par[id[i]]]+=size[id[i]];
}
int flag[MAXN<<1];
inline void Query()
{
int now=root,L=0,ans=0;
for (int i=1; i<=N+N; i++)
{
int c=S[i]-'a'+1;
if (son[now][c]) L++,now=son[now][c];
else
{
while (now && !son[now][c]) now=par[now];
if (!now)
now=root,L=0;
else
L=len[now]+1,now=son[now][c];
}
if (i>N && L>=N)
{
int tmp=now;
while (tmp && !(N>=len[par[tmp]]+1 && N<=len[tmp]))
tmp=par[tmp];
if (!tmp) tmp=root;
if (flag[tmp]!=Q+1) ans+=size[tmp],flag[tmp]=Q+1;
}
}
printf("%d\n",ans);
}
}using namespace SAM;
int main()
{
scanf("%s",S+1); N=strlen(S+1);
SAM::Build(); SAM::Pre();
scanf("%d",&Q);
while (Q--)
{
scanf("%s",S+1); N=strlen(S+1);
for (int i=1; i<=N; i++) S[N+i]=S[i];
SAM::Query();
}
return 0;
}
【Codeforces235C】Cyclical Quest 后缀自动机的更多相关文章
- Codeforces 235C Cyclical Quest - 后缀自动机
Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in ...
- CF 235C. Cyclical Quest [后缀自动机]
题意:给一个主串和多个询问串,求询问串的所有样子不同的周期同构出现次数和 没有周期同构很简单就是询问串出现次数,|Right| 有了周期同构,就是所有循环,把询问串复制一遍贴到后面啊!思想和POJ15 ...
- Codeforces Round #146 (Div. 1) C - Cyclical Quest 后缀自动机+最小循环节
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk mak ...
- 【CF235C】Cyclical Quest(后缀自动机)
[CF235C]Cyclical Quest(后缀自动机) 题面 洛谷 题解 大致翻译: 给定一个串 然后若干组询问 每次也给定一个串 这个串可以旋转(就是把最后一位丢到最前面这样子) 问这个串以及其 ...
- 【CodeForces - 235C】Cyclical Quest 【后缀自动机】
题意 给出一个字符串s1和q个询问,每个询问给出一个字符串s2,问这个询问的字符串的所有不同的周期串在s1中出现的次数的和. 分析 对于s1建后缀自动机.对于询问的每个字符串s2,我们按照处理循环串的 ...
- Cyclical Quest CodeForces - 235C (后缀自动机)
Cyclical Quest \[ Time Limit: 3000 ms\quad Memory Limit: 524288 kB \] 题意 给出一个字符串为 \(s\) 串,接下来 \(T\) ...
- Cyclical Quest CodeForces - 235C 后缀自动机
题意: 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数, 圆环匹配的意思是将该子串拆成两段再首位交换相接的串和母串匹配,比 如aaab变成baaa,abaa,aaba再进行匹配. ...
- 后缀自动机(SAM)
*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...
- 【学习笔记】浅析后缀自动机(SAM)及基础应用
解决子串相关问题的强大工具 我们知道一个长度为 \(n\) 的字符串中所有的子串数目为 \(O(n^2)\) 个,这很大程度上限制了我们对某些子串相关问题的研究.所以有没有解决方案,使得我们可以在可承 ...
随机推荐
- 《连载 | 物联网框架ServerSuperIO教程》- 11.实现设备(驱动)与设备(驱动)交互和级联控制。注:设备驱动模拟金三与普京的对话
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- SpringMVC的执行流程(二)
文字解析: 1.客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配 DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交 ...
- window下的各种宽高度小结
详细的请打开这里看console.log window.innerWidth: 文档显示区(body)的宽度window.innerHeight 文档显示区(body)的高度window.outr ...
- 【前端优化之渲染优化】大屏android手机动画丢帧的背后
前言 上周我与阿里的宇果有一次技术的交流,然后对天猫H5站点做了一些浅层次的分析,后面点时间基本天天都会有联系,中途聊了一些技术细节.聊了双方团队在干什么,最后聊到了前端优化.因为我本身参与了几次携程 ...
- iOS从零开始学习直播之音频1.播放本地音频文件
现在直播越来越火,俨然已经成为了下一个红海.作为一个资深码农(我只喜欢这样称呼自己,不喜欢别人这样称呼我),我必须赶上时代的潮流,开始研究视频直播.发现视屏直播类的文章上来就讲拉流.推流.采集.美 ...
- 解决问题:无法对 System程序集 添加Fakes程序集
为了在单元测试中指定DateTime.Now的值,我采用Microsoft Fakes技术的Shim. 主要参考了园里的http://www.cnblogs.com/FreeDong/p/335311 ...
- 开窗函数 First_Value 和 Last_Value
在Sql server 2012里面,开窗函数丰富了许多,其中带出了2个新的函数 First_Value 和 Last Value .现在来介绍一下这2个函数的应用场景. 首先分析一下First_Va ...
- k近邻算法(knn)的c语言实现
最近在看knn算法,顺便敲敲代码. knn属于数据挖掘的分类算法.基本思想是在距离空间里,如果一个样本的最接近的k个邻居里,绝大多数属于某个类别,则该样本也属于这个类别.俗话叫,"随大流&q ...
- 简单配置 nginx 反向代理
# Nginx 域名反向代理配置# 安装nginx yum install nginx -y# 修改配置文件 进入配置文件目录 cd /etc/nginx/conf.d 新建配置文件以.conf结尾 ...
- javascript判断是否为闰年
//判断年份year是否为闰年,是闰年则返回true,否则返回false function isLeapYear(year){ var a = year % 4; var b = year % 100 ...