解法一【后缀数组+二分】见【这里】。
把
n
个串的广义后缀自动机建出来,然后统计每个点所代表的串出现的次数。这个数值相当于它的
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=300010;
char s[maxn];
int trie[maxn][27],trans[maxn][27],fail[maxn],val[maxn],num[maxn],
que[maxn],node[maxn],L[maxn],R[maxn],pre[maxn],sum[maxn],ord[maxn],
res[maxn],cnt[maxn],
n,m,tot=1,clo;
LL ans[maxn];
vector<int> v[maxn],id[maxn],son[maxn];
vector<pair<int,int> > qry[maxn];
int add(int last,int x)
{
int p=last,np,q,nq;
val[np=++tot]=val[last]+1;
while (p&&!trans[p][x])
{
trans[p][x]=np;
p=fail[p];
}
if (!p) fail[np]=1;
else
{
q=trans[p][x];
if (val[q]==val[p]+1) fail[np]=q;
else
{
val[nq=++tot]=val[p]+1;
fail[nq]=fail[q];
fail[q]=fail[np]=nq;
for (int i=1;i<=26;i++) trans[nq][i]=trans[q][i];
while (p&&trans[p][x]==q)
{
trans[p][x]=nq;
p=fail[p];
}
}
}
return np;
}
void dfs1(int x,int y)
{
id[y]=v[x];
for (int i=1;i<=26;i++)
if (trie[x][i]) dfs1(trie[x][i],trans[y][i]);
}
void dfs2(int u)
{
ord[L[u]=++clo]=u;
for (vector<int>::iterator it=son[u].begin();it!=son[u].end();++it) dfs2(*it);
R[u]=clo;
qry[R[u]].push_back(make_pair(u,L[u]));
}
void dfs3(int x,int y)
{
for (vector<int>::iterator it=v[x].begin();it!=v[x].end();++it)
ans[*it]+=res[y];
for (int i=1;i<=26;i++)
if (trie[x][i]) dfs3(trie[x][i],trans[y][i]);
}
void dec(int k)
{
for (;k<=clo;k+=k&-k) sum[k]--;
}
void inc(int k)
{
for (;k<=clo;k+=k&-k) sum[k]++;
}
int query(int k)
{
int ret=0;
for (;k;k-=k&-k) ret+=sum[k];
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t1=0,l,p,hd,tl,u,mx=0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
l=strlen(s+1);
p=0;
for (int j=1;j<=l;j++)
{
if (!trie[p][s[j]-'a'+1]) trie[p][s[j]-'a'+1]=++t1;
p=trie[p][s[j]-'a'+1];
v[p].push_back(i);
}
}
node[0]=1;
que[hd=tl=1]=0;
while (hd<=tl)
{
u=que[hd++];
for (int i=1;i<=26;i++)
if (trie[u][i])
{
node[trie[u][i]]=add(node[u],i);
que[++tl]=trie[u][i];
}
}
dfs1(0,1);
for (int i=1;i<=tot;i++) son[fail[i]].push_back(i);
dfs2(1);
for (int i=1;i<=clo;i++)
{
for (vector<int>::iterator it=id[ord[i]].begin();it!=id[ord[i]].end();++it)
{
if (pre[*it]) dec(pre[*it]);
pre[*it]=i;
inc(i);
}
for (vector<pair<int,int> >::iterator it=qry[i].begin();it!=qry[i].end();++it)
num[(*it).first]=query(i)-query((*it).second-1);
}
for (int i=1;i<=tot;i++)
if (num[i]>=m) res[i]=val[i]-val[fail[i]];
for (int i=1;i<=tot;i++)
{
mx=max(mx,val[i]);
cnt[val[i]]++;
}
for (int i=1;i<=mx;i++) cnt[i]+=cnt[i-1];
for (int i=1;i<=tot;i++) que[cnt[val[i]]--]=i;
for (int i=1;i<=tot;i++) res[que[i]]+=res[fail[que[i]]];
dfs3(0,1);
for (int i=1;i<=n;i++) printf("%lld ",ans[i]);
}