CF235C Cyclical Quest
题意
显然先把\(S\)塞进\(SAM\)中,之后处理每个询问。
对于一个询问,我们自然不能枚举所有的循环串,于是我们考虑在匹配的过程中删去首字符,加入尾字符。
先匹配好,求一波答案。之后开始删一个首字符,加一个尾字符,之后再统计,直到所有串统计完。
维护当前在哪个节点\(now\)和匹配的长度\(len\)。
删一个首字符:
\(len--\)。
假如\(len=len_{fa_{now}}\),就向上跳,使\(now=fa_{now}\)。
添一个尾字符:
一直跳,直到\(now\)有这个字符的出边,中途跳一次令\(len=len_{now}\)。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,Q,cnt,tim;
int head[maxn<<1];
char s[maxn];
struct edge{int to,nxt;}e[maxn<<2];
struct SAM
{
int last,tot;
int fa[maxn<<1],len[maxn<<1],cnt[maxn<<1],vis[maxn<<1];
int ch[maxn<<1][30];
inline void init(){last=tot=1;}
inline void add(int c)
{
int now=++tot;cnt[now]=1;len[now]=len[last]+1;
int p=last;last=now;
while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
if(!p){fa[now]=1;return;}
int q=ch[p][c];
if(len[q]==len[p]+1)fa[now]=q;
else
{
int nowq=++tot;len[nowq]=len[p]+1;
memcpy(ch[nowq],ch[q],sizeof(ch[q]));
fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
}
}
}sam;
inline void add(int u,int v)
{
e[++cnt].nxt=head[u];
head[u]=cnt;
e[cnt].to=v;
}
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
dfs(e[i].to),sam.cnt[x]+=sam.cnt[e[i].to];
}
inline int solve(char* s)
{
tim++;
int len=strlen(s+1),ans=0,now=1,nowlen=0;
for(int i=1;i<=len;i++)
{
int c=s[i]-'a';
while(now>1&&!sam.ch[now][c])now=sam.fa[now],nowlen=sam.len[now];
if(sam.ch[now][c])now=sam.ch[now][c],nowlen++;
}
if(nowlen==len&&sam.vis[now]!=tim)sam.vis[now]=tim,ans+=sam.cnt[now];
for(int i=1;i<len;i++)
{
int c=s[i]-'a';
while(now>1&&!sam.ch[now][c])now=sam.fa[now],nowlen=sam.len[now];
if(sam.ch[now][c])now=sam.ch[now][c],nowlen++;
if(nowlen>len&&(--nowlen)==sam.len[sam.fa[now]])now=sam.fa[now];
if(nowlen==len&&sam.vis[now]!=tim)sam.vis[now]=tim,ans+=sam.cnt[now];
}
return ans;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
sam.init();
for(int i=1;i<=n;i++)sam.add(s[i]-'a');
for(int i=2;i<=sam.tot;i++)add(sam.fa[i],i);
dfs(1);
scanf("%d",&Q);
while(Q--)
{
scanf("%s",s+1);
printf("%d\n",solve(s));
}
return 0;
}