2018.12.22 bzoj3277: 串(后缀自动机+启发式合并)

时间:2021-08-26 04:46:35

传送门

这道题是一模一样的。

于是本蒟蒻又写了一遍10min1A庆祝

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=2e5+5;
typedef long long ll;
int T,k;
string s[N];
struct SAM{
	int last,tot,len[N],son[N][26],link[N],val[N];
	vector<int>e[N];
	set<int>S[N];
	SAM(){last=tot=1,len[0]=-1,fill(son[0],son[0]+26,1);}
	inline void expand(int x,int id){
		int p=last,np=++tot;
		S[last=np].insert(id),len[np]=len[p]+1;
		while(!son[p][x])son[p][x]=np,p=link[p];
		if(!p){link[np]=1;return;}
		int q=son[p][x],nq;
		if(len[q]==len[p]+1){link[np]=q;return;}
		len[nq=++tot]=len[p]+1,memcpy(son[nq],son[q],sizeof(son[q])),link[nq]=link[q],link[q]=link[np]=nq;
		while(son[p][x]==q)son[p][x]=nq,p=link[p];
	}
	inline void merge(int x,int y){
		if(S[x].size()<S[y].size())swap(S[x],S[y]);
		for(set<int>::iterator it=S[y].begin();it!=S[y].end();++it)S[x].insert(*it);
	}
	inline void dfs(int p){for(ri i=0;i<e[p].size();++i)dfs(e[p][i]),merge(p,e[p][i]);val[p]=S[p].size();}
	inline void solve(){for(ri i=1;i<=tot;++i)if(link[i])e[link[i]].push_back(i);dfs(1);}
	inline ll query(int id){
		int p=1,up=s[id].size();
		ll ret=0;
		for(ri i=0;i<up;++i){
			p=son[p][s[id][i]-'a'];
			while(val[p]<k)p=link[p];
			ret+=len[p];
		}
		return ret;
	}
}sam;
int main(){
	scanf("%d%d",&T,&k);
	if(k>T){for(ri i=1;i<=T;++i)cout<<"0 ";return 0;}
	for(ri i=1,n;i<=T;++i){
		cin>>s[i],n=s[i].size();
		for(ri j=0;j<n;++j)sam.expand(s[i][j]-'a',i);
		sam.last=1;
	}
	sam.solve();
	for(ri i=1;i<=T;++i)cout<<sam.query(i)<<' ';
	return 0;
}