[CF235C] Cyclical Quest

\(\text{Problem}:\)Cyclical Quest

\(\text{Solution}:\)

对文本串 \(S\) 建出 \(\text{SAM}\)。对查询串 \(T\),将其复制为 \(T+T\) 的形式,并在 \(S\) 上匹配,如果对于当前状态 \(x\),长度区间 \([\text{len(link}(x))+1,\text{len}(x)]\) 包含了 \(\lvert T\rvert\),那么对答案的贡献为 \(size_{x}\),即 \(S\) 在状态 \(x\) 上每个子串的出现次数。同时,对匹配到的相同状态去重,只需在有贡献的状态上打 \(tag\) 即可。时间复杂度 \(O(n)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=2000010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
char s[N],t[N];
int n,m,book[N],siz[N],vis[N];
int head[N],maxE; struct Edge { int nxt,to; }e[N<<1];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
struct SAM
{
	int link[N],len[N],ch[N][26];
	int tot,lst;
	inline SAM() { tot=lst=1; link[1]=len[1]=0; memset(ch[1],0,sizeof(ch[1])); }
	inline void Extend(int c)
	{
		int now=++tot;
		int p=lst;
		book[now]=1;
		while(p && !ch[p][c]) ch[p][c]=now, p=link[p];
		len[now]=len[lst]+1;
		if(!p) { lst=now, link[now]=1; return; }
		int q=ch[p][c];
		if(len[q]==len[p]+1) link[now]=q;
		else
		{
			int nq=++tot;
			len[nq]=len[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			link[nq]=link[q];
			link[q]=link[now]=nq;
			while(p && ch[p][c]==q) ch[p][c]=nq, p=link[p];
		}
		lst=now;
	}
	inline void Renew()
	{
		for(ri int i=1;i<=tot;i++) link[i]=len[i]=0, memset(ch[i],0,sizeof(ch[i]));
		tot=lst=1; maxE=0;
	}
}A;
void DFS(int x)
{
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		DFS(v);
		siz[x]+=siz[v];
	}
	siz[x]+=book[x];
}
signed main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for(ri int i=1;i<=n;i++) A.Extend(s[i]-'a');
	for(ri int i=2;i<=A.tot;i++) Add(A.link[i],i);
	DFS(1);
	vector<int> g;
	for(ri int T=read();T;T--)
	{
		scanf("%s",t+1);
		m=strlen(t+1);
		int flg=1;
		for(ri int i=m+1;i<=m+m;i++) t[i]=t[i-m], flg&=(t[1]==t[i]);
		int now=0,sta=1;
		long long ans=0;
		for(ri int i=1;i<m+m;i++)
		{
			int p=t[i]-'a';
			while(sta && !A.ch[sta][p]) sta=A.link[sta], now=A.len[sta];
			if(!sta) sta=1;
			if(A.ch[sta][p]) sta=A.ch[sta][p], now++;
			while(sta && A.len[A.link[sta]]>=m) now=A.len[A.link[sta]], sta=A.link[sta];
			if(now>=m&&!vis[sta]) ans+=siz[sta], vis[sta]=1, g.eb(sta);
		}
		printf("%lld\n",ans);
		for(auto i:g) vis[i]=0;
		g.clear();
	}
	return 0;
}
posted @ 2021-03-29 18:09  zkdxl  阅读(39)  评论(0编辑  收藏  举报