题解:
后缀数组的做法就不说了,又慢又长。
考虑后缀自动机,把这几个串同时拿出来搞。
多个串怎么建呢? 一种方法是直接每个字符中串一个字符,不过这样会导致字符集变大,还有一种方法是直接每次暴力重置last为root,插入的时候判一下是否有转移。
我们还要统计一个点对于每个串的出现次数,这个也有两种方法,一种是离线之后用树状数组搞,具体细节就不说了。 还有一种复杂度不知道正不正确的方法,就是每次插入完后直接暴力跳fail链统计,注意打个标号,如果已经被这个串统计过就不继续跳fail了。。
总之复杂度很像 O(n) O ( n ) 的,而且也不好卡。这种写法比后缀数组快了10多倍。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
int n,k,last=1,l[N],ld[N],fail[N],son[N][26],sze[N],tot;
long long f[N];
int bg[N],ed[N],a[N],totlen;
char ch[N];
inline void extend(int c,int id) {
if(son[last][c]) {
int p=son[last][c];
if(l[p]==l[last]+1) last=p;
else {
int np=++tot; l[np]=l[last]+1;
sze[np]=sze[p]; ld[np]=ld[p];
memcpy(son[np],son[p],sizeof(son[p]));
fail[np]=fail[p]; fail[p]=np;
while(last&&son[last][c]==p) son[last][c]=np,last=fail[last];
last=np;
}
} else {
int p=++tot; l[p]=l[last]+1;
while(last&&!son[last][c]) son[last][c]=p,last=fail[last];
if(!last) fail[p]=1;
else {
int q=son[last][c];
if(l[q]==l[last]+1) fail[p]=q;
else {
int np=++tot; l[np]=l[last]+1;
sze[np]=sze[q]; ld[np]=ld[q];
memcpy(son[np],son[q],sizeof(son[q]));
fail[np]=fail[q]; fail[q]=np; fail[p]=np;
while(last&&son[last][c]==q) son[last][c]=np,last=fail[last];
}
}
last=p;
}
for(int now=last;now&&ld[now]!=id;now=fail[now]) {
ld[now]=id; ++sze[now];
}
}
inline void insert(int id) {
last=1; int len=strlen(ch+1);
for(int i=1;i<=len;i++)
extend(ch[i]-'a',id);
bg[id]=totlen+1; ed[id]=totlen+len;
for(int i=1;i<=len;i++) a[i+totlen]=ch[i]-'a';
totlen=ed[id];
}
int que[N],tl,deg[N];
int main() {
scanf("%d%d",&n,&k); tot=1;
for(int i=1;i<=n;i++) {
scanf("%s",ch+1);
insert(i);
}
for(int i=1;i<=tot;i++){ if(sze[i]>=k) f[i]=(l[i]-l[fail[i]]); }
for(int i=1;i<=tot;i++) if(fail[i]) ++deg[fail[i]];
for(int i=1;i<=tot;i++) if(!deg[i]) que[++tl]=i;
for(int i=1;i<=tl;i++)
if(fail[que[i]])
if(!(--deg[fail[que[i]]]))
que[++tl]=fail[que[i]];
for(int i=tl;i>=1;i--) if(fail[que[i]]) f[que[i]]+=f[fail[que[i]]];
for(int i=1;i<=n;i++) {
long long sum=0; int nowpos=1;
for(int j=bg[i];j<=ed[i];j++) {
nowpos=son[nowpos][a[j]];
sum+=f[nowpos];
}
printf("%lld ",sum);
}
}