CF235C Cyclical Quest 题解

Description

题目来源-洛谷

题目来源-CF

定义文本串 \(S'\) 和 匹配串 \(x_i\) 同构:\(x_i\) 经过循环移位(可以不移)与 \(S'\) 相同。

给定一个 \(S\) 和许多 \(x_i\),询问对于每一个 \(x_i\) 有多少个 \(S\) 的子串 \(S'\)\(x_i\) 同构。

Solution

先对 \(S\) 构建后缀自动机

首先,题目中的问题可以转化为:设 \(l_i=len(x_i)\),将 \(x_i\) 自我复制一份后,有多少个 \(S\)\(x_i\) 之间的长为 \(l_i\) 的公共子串。

接下来使用一个 SAM 上很重要的技巧:把 SAM 当作 AC 自动机一样进行字符串匹配。

匹配方法:对于当前已经匹配到的状态,如果有转移边,就直接转移并将当前匹配长度 \(+1\),否则一直跳 link 指针,并修改当前匹配长度为当前状态的 len。

于是直接匹配就好,注意同一个节点的贡献只能算一次,打个标记就好。

时间复杂度 \(O(\left| S \right| + \sum \left| x_i \right|)\)

#include<bits/stdc++.h>
#define N 1000005
#define F(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
struct state{int to[26],link,cnt,len;}st[N<<1];
int sz,lst,n;
long long ans;
string s,x;
inline void insert(int c){
	int cur=++sz,p=lst;
	st[cur].len=st[lst].len+1,st[cur].cnt=1,lst=cur;
	while(p!=-1&&!st[p].to[c])st[p].to[c]=cur,p=st[p].link;
	if(p==-1)return;
	int q=st[p].to[c];
	if(st[p].len+1==st[q].len)return st[cur].link=q,void();
	int clone=++sz;
	st[clone]=st[q],st[clone].len=st[p].len+1,st[clone].cnt=0;
	while(p!=-1&&st[p].to[c]==q)st[p].to[c]=clone,p=st[p].link;
	st[cur].link=st[q].link=clone;
}
vector<int>t[N<<1];
inline void dfs(int u){for(int v:t[u])dfs(v),st[u].cnt+=st[v].cnt;}
int stk[N<<1],tt;
bool vis[N<<1];
int main(){
	st[0].link=-1;
	cin>>s>>n;
	F(i,0,(int)s.length()-1)insert(s[i]-'a');
	F(i,1,sz)t[st[i].link].push_back(i);
	dfs(0);
	while(n--){
		cin>>x;
		ans=0;
		int u=0;
		tt=0;
		int len=0,L=x.length();
		F(i,0,(int)x.length()-1){
			int c=x[i]-'a';
			while(u&&!st[u].to[c])u=st[u].link,len=st[u].len;
			if(st[u].to[c])len++,u=st[u].to[c];
		}
		F(i,0,(int)x.length()-1){
			int c=x[i]-'a';
			while(u&&!st[u].to[c])u=st[u].link,len=st[u].len;
			if(st[u].to[c])len++,u=st[u].to[c];
			if(len>L){
				len--;
				if(len==st[st[u].link].len)u=st[u].link;
			}
			if(len==L)stk[++tt]=u,vis[u]=1;
		}
		F(i,1,tt)if(vis[stk[i]])vis[stk[i]]=0,ans+=st[stk[i]].cnt;//,cout<<stk[i]<<' '<<st[stk[i]].cnt<<' '<<st[stk[i]].len<<'\n';;
		cout<<ans<<'\n';
	}
}
posted @ 2025-06-17 11:59  linjingxiang  阅读(14)  评论(0)    收藏  举报