传送门
跟这道题是一模一样的。
于是本蒟蒻又写了一遍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;
}