Codeforces 235C
题目大意:
给定一个字符串,接下来再给n个字符串,求原字符串中含有多少个当前给定字符串的循环同构体的字符串的个数
以初始字符串构建后缀自动机,在自动机上前进的时候,比如当前需要匹配的字符串为aba,到达某个状态点S
我们所希望知道的所有aba出现的次数,因为aba最终到达的是点S,其实可以理解为整个后缀自动机通过f(父指针)形成了一棵后缀树
而这个S是后缀树上的叶子节点,那么上方所有的父亲节点都包含这个S,我们只需要找到最顶端的能达到aba状态的根节点,在根状态上记录其下方出现此后缀总共出现的个数
那么首先将后缀自动机拓扑排序,然后节点逆向访问,不断更新父亲节点的信息,用节点上的cnt变量记录当前节点作为根节点时所能得到的后缀的总个数
对于每个当前每个给定的字符串,因为要求循环同构,那么再连接一个相同的字符串在其后方,然后正常在后缀自动机上跑,当匹配到的长度大于len时,说明这个字符串中包含了循环同构体,我们就要不断逆向通过父亲回溯到根节点,这个根节点表示所能达到的长度尽可能小却仍旧大于等于len即可,因为这样的点是当前匹配所有作为大于len的后缀的节点的祖先。然后通过当前节点的flag标记判断当前节点是否被访问过来获取其中的cnt
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define N 1000010
#define ll long long
struct SamNode{
SamNode *son[] , *f;
int l , cnt , flag;
void init(){
for(int i= ; i< ; i++) son[i] = NULL;
f=NULL;
l = flag = cnt = ;
}
}sam[N<<] , *root , *last , *b[N<<]; int cnt , n , num[N];
char s[N] , str[N]; void add(int x)
{
SamNode *p = &sam[++cnt] , *jp = last;
p->l = jp->l+ ;
last = p;
for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x] = p;
if(!jp) p->f = root;
else{
if(jp->l+ == jp->son[x]->l) p->f = jp->son[x];
else{
SamNode *r = &sam[++cnt] , *q = jp->son[x];
*r = *q;
r->l = jp->l+;
p->f = q->f = r;
for( ; jp&&jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
}
}
} void solve()
{
scanf("%d" , &n);
for(int mark= ; mark<=n ; mark++){
scanf("%s" , str);
int len = strlen(str) , ret = ;
ll ans = ;
SamNode *cur = root;
for(int i= ; i<*len ; i++){
int x = (i>=len?str[i-len]:str[i])-'a';
if(cur->son[x]){
cur = cur->son[x];
ret++;
}
else{
while(cur && !cur->son[x]) cur = cur->f;
if(!cur) cur=root , ret=;
else{
ret = cur->l+;
cur=cur->son[x];
}
}
while(cur->f&&cur->f->l>=len){
cur = cur->f;
ret = cur->l;
}
if(ret>=len && cur->flag!=mark) cur->flag=mark , ans= ans+cur->cnt;
}
printf("%I64d\n" , ans);
}
} int main()
{
// freopen("a.in" , "r", stdin);
scanf("%s" , s);
int len = strlen(s);
sam[].init();
root = last = &sam[cnt=];
for(int i= ; i<len ; i++) add(s[i]-'a');
for(int i= ; i<=cnt ; i++) num[sam[i].l]++;
for(int i= ; i<=len ; i++) num[i] += num[i-];
for(int i= ; i<=cnt ; i++) b[--num[sam[i].l]] = &sam[i];
SamNode *cur = root;
for(int i= ; i<len ; i++){
cur = cur->son[s[i]-'a'];
cur->cnt++;
}
for(int i=cnt ; i> ; i--) b[i]->f->cnt+=b[i]->cnt , b[i]->flag=;
solve();
return ;
}
Codeforces 235C的更多相关文章
- Codeforces 235C. Cyclical Quest
传送门 写的时候挺蛋疼的. 刚开始的时候思路没跑偏,无非就是建个SAM然后把串开两倍然后在SAM上跑完后统计贡献.但是卡在第二个样例上就是没考虑相同的情况. 然后开始乱搞,发现会出现相同串的只有可能是 ...
- Codeforces 235C Cyclical Quest - 后缀自动机
Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in ...
- CodeForces 235C Cyclical Quest(后缀自动机)
[题目链接] http://codeforces.com/contest/235/problem/C [题目大意] 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数,圆环匹配的意思是 ...
- Codeforces 235C Cyclical Quest 字符串 SAM KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF235C.html 题目传送门 - CF235C 题意 给定一个字符串 $s$ ,多组询问,每组询问的形式为 ...
- 【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)学习指南
*在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂 ...
随机推荐
- [html] src与href的区别
src用于替换当前元素,href用于在当前文档和引用资源之间确立联系. src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置:在请求src资源时会将其指向的资源下 ...
- 转:c的回归-云风
C 的回归 周末出差,去另一个城市给公司的一个项目解决点问题.回程去机场的路上,我用手机上 google reader 打发时间.第一眼就看到孟岩大大新的一篇:Linux之父话糙理不糙 .主题是 C ...
- 使用命令参数方式指定log4j配置文件
http://blog.csdn.net/changong28/article/details/39717209 ******************************************* ...
- control file sequential read 等待事件
可能的原因 control file sequential read Reading from the control file. This happens in many cases. For ex ...
- China Brain Project: Basic Neuroscience, Brain Diseases, and Brain-Inspired Computing
日前,中国科学院神经科学研究所.中国科学院脑科学与智能技术卓越创新中心.香港科技大学生命科学部和分子神经科学国家重点实验室.中国科技大学自动化研究所在 Cell 上联合发表了一篇概述论文<Chi ...
- 在XP下把win7安装到VHD,内存足够大可以RAMOS
在XP下把win7安装到VHD,内存足够大可以RAMOS1.用DiskGenius创建VHD固定大小磁盘文件,以win7vhd.vhd为例,然后进行分区格式化,格式化时启用NTFS压缩.2.进入WIN ...
- Directory.GetCurrentDirectory和Application.StartupPath的区别
System.IO.Directory.GetCurrentDirectory()方法用于获得应用程序当前工作目录.System.Windows.Forms.Application.StartupPa ...
- 《Java程序设计》第四周学习总结
20145224-陈颢文 <Java程序设计>第四周学习总结 教材学习内容总结 第六章 继承与多态 ·继承就是面向对象中,子类继承父类,避免重复的行为定义.重复再程序设计上是非常不好的信号 ...
- 《javascript高级程序设计》第三章 Language Basics
3.1 语法syntax 3.1.1 区分大小写case-sensitivity 3.1.2 标识符identifiers 3.1.3 注释comments 3.1.4 严格模式strict mode ...
- python中join的用法
str.join(sequence) # 将序列中的元素以str字符连接生成一个新的字符串 list1 = ['a', 'b', 'c'] new_str = '-'.join(list1) # 输出 ...