思路

后缀自动机求最长循环串

首先有一个常用的处理技巧,将串复制一遍,长度大于n的子串中就包含了一组循环子串

然后是后缀自动机如何处理最长公共子串的问题

维护两个变量,u和l,u代表当前位置的最长公共子串在哪个状态中,l代表当前位置的最长公共子串的长度

然后如果当前位置有向T[i+1]转移的路径,则转移,u=trans[u][T[i]],l=l+1

如果当前位置没有转移路径,则沿suflink回跳到有转移路径的状态,如果跳到初始状态仍然没有满足条件的节点,就变成初始条件即可

注意两个地方,第一个是一个状态可能被多次统计,需要标记一下,第二个是如果l>lent,有可能=lent的状态在前面,且出现次数更多,所以需要沿suflink跳到第一个maxlen>=lent的位置

不要用memset,会T

代码

#include <queue>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MAXN = 1001000*2;
int maxlen[MAXN],endpos[MAXN],suflink[MAXN],trans[MAXN][26],cnt,vis[MAXN],in[MAXN],n,ispre[MAXN],lens,lent,ans;
char s[MAXN],t[MAXN];
int new_state(int _maxlen,int *_trans,int _suflink){
++cnt;
maxlen[cnt]=_maxlen;
if(_trans)
for(int i=0;i<26;i++)
trans[cnt][i]=_trans[i];
suflink[cnt]=_suflink;
return cnt;
}
int add_len(int u,int c){
int z=new_state(maxlen[u]+1,NULL,0);
ispre[z]=1;
while(u&&(!trans[u][c])){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=new_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[v]=suflink[z]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
int q[MAXN*3],head=1,tail=0;
void topu(void){
head=1,tail=0;
for(int i=1;i<=cnt;i++)
if(suflink[i]>=1)
in[suflink[i]]++;
for(int i=1;i<=cnt;i++)
if(!in[i])
q[++tail]=i;
while(head<=tail){
int x=q[head];
head++;
endpos[x]+=ispre[x];
endpos[suflink[x]]+=endpos[x];
in[suflink[x]]--;
if(!in[suflink[x]])
q[++tail]=suflink[x];
}
}
void work(void){
ans=0;
for(int i=1;i<=cnt;i++)
vis[i]=false;
int u=1,l=0;
for(int i=1;i<=lent*2;i++){
while(u!=1&&(!trans[u][t[i]-'a'])){
u=suflink[u],l=maxlen[u];
}
if(trans[u][t[i]-'a']){
u=trans[u][t[i]-'a'];
l=l+1;
}
else{
u=1;
l=0;
}
if(l>lent){
while(maxlen[suflink[u]]>=lent)
u=suflink[u],l=maxlen[u];
}
if(l>=lent&&!vis[u]){
vis[u]=true;
ans+=endpos[u];
}
}
}
signed main(){
scanf("%s",s+1);
lens=strlen(s+1);
int pre=1;
cnt=1;
for(int i=1;i<=lens;i++)
pre=add_len(pre,s[i]-'a');
topu();
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%s",t+1);
lent=strlen(t+1);
for(int j=1;j<=lent;j++){
t[j+lent]=t[j];
}
work();
printf("%lld\n",ans);
}
return 0;
}

HIHOcoder1465 后缀自动机五·重复旋律8的更多相关文章

  1. hihoCoder #1465 : 后缀自动机五·重复旋律8

    http://hihocoder.com/problemset/problem/1465 求S的循环同构串在T中的出现次数 将串S变成SS 枚举SS的每个位置i,求出以i结尾的SS的子串 与 T的最长 ...

  2. hihocoder 后缀自动机五·重复旋律8 求循环同构串出现的次数

    描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi发现旋律可以循环,每次把一段旋律里面最前面一个音换到最后面就成为了原旋律的“循环相似旋律”,还可以 ...

  3. hihoCoder.1465.后缀自动机五 重复旋律8(后缀自动机)

    题目链接 \(Description\) 给定母串S,求模式串的循环同构串在S中的出现次数. \(Solution\) 将模式串s复制一遍,在母串的SAM上匹配,记录以每个位置作为后缀所能匹配的最大长 ...

  4. hiho一下第131周 后缀自动机二·重复旋律8(循环相似子串)

    后缀自动机五·重复旋律8 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi ...

  5. BZOJ 后缀自动机四·重复旋律7

    后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的 ...

  6. hihoCoder 后缀自动机三·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  7. hihoCoder #1445 : 后缀自动机二·重复旋律5

    #1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...

  8. HDU_1457_后缀自动机四·重复旋律7

    #1457 : 后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成 ...

  9. hihoCoder_1449_后缀自动机三·重复旋律6

    #1449 : 后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...

随机推荐

  1. I Count Tow Three

    #include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#inclu ...

  2. Explorer Bo (思维 + 树链剖分)

    题意:求用最少的链覆盖所有的边用最少的总链长度. 思路:为了使得使用的链最少,我们可以知道使用的数量应该是(子叶 + 1)/ 2. 画图可知:当节点下的边数是偶数时,为了将该父节点上的边给连接上,所以 ...

  3. 即时通信系统中实现聊天消息加密,让通信更安全【低调赠送:C#开源即时通讯系统(支持广域网)——GGTalk4.5 最新源码】

    在即时通讯系统(IM)中,加密重要的通信消息,是一个常见的需求.尤其在一些政府部门的即时通信软件中(如税务系统),对即时聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据.我在最新 ...

  4. Runtime(IV) - 序列化与反序列化

    准备条件 父类 Biology Biology.h #import <Foundation/Foundation.h> @interface Biology : NSObject { NS ...

  5. 【impala学习之一】impala

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 CM5.4 一.ImpalaImpala是基于Hive的大数 ...

  6. spring4.0.0 源码导入eclipse(sts)

    其余步骤请见:http://www.cnblogs.com/xiluhua/p/7450972.html 执行 gradle eclipse -x :eclipse 报错: 解决办法: 找到 行,注释 ...

  7. 什么是ASCII

    以下内容是从百度百科学的 1)ASCII(American Standard Code for Information Interchange:美国信息交换标准代码) 2)产生原因 在计算机中,所有的 ...

  8. Ant打包可运行的Jar包(加入第三方jar包)

    本章介绍使用ant打包可运行的Jar包. 打包jar包最大的问题在于如何加入第三方jar包使得jar文件可以直接运行.以下用一个实例程序进行说明. 程序结构: 关键代码: package com.al ...

  9. Linux基础命令---显示登录用户logname

    logname 显示当前登录的用户名称.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法        logname   2 ...

  10. golang学习笔记8 beego参数配置 打包linux命令

    golang学习笔记8 beego参数配置 打包linux命令 参数配置 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/docs/mvc/contro ...