[BZOJ3277]串 广义后缀自动机

3277: 串

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 811  Solved: 329
[Submit][Status][Discuss]

Description

字符串是oi界常考的问题。现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中
至少k个字符串的子串(注意包括本身)。

Input

第一行两个整数n,k。
接下来n行每行一个字符串。
n,k,l<=100000

Output

输出一行n个整数,第i个整数表示第i个字符串的答案。

Sample Input

3 1
abc
a
ab

Sample Output

6 1 3

HINT

 

Source

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstdio>
 7 #define maxn 200005
 8 using namespace std;
 9 int n,k;
10 long long c[maxn];
11 long long ans[maxn]; 
12 struct data {
13     long long son[maxn][26],link[maxn],step[maxn],last,cnt,t[maxn],size[maxn],tp[maxn];
14     data() {last=cnt=1;}
15     void extend(int x,int id) {
16         int p=last,np=last=++cnt;step[np]=step[p]+1;t[np]=id;
17         while(p&&!son[p][x]) son[p][x]=np,p=link[p];
18         if(!p) link[np]=1;
19         else {
20             int q=son[p][x];
21             if(step[q]==step[p]+1) link[np]=q;
22             else {
23                 int nq=++cnt;
24                 memcpy(son[nq],son[q],sizeof(son[q]));
25                 step[nq]=step[p]+1;
26                 link[nq]=link[q];link[np]=link[q]=nq;size[nq]=size[q];tp[nq]=tp[q];
27                 while(p&&son[p][x]==q) son[p][x]=nq,p=link[p];
28             }
29         }
30         for(int i=np;i&&tp[i]!=id;i=link[i]) size[i]++,tp[i]=id;
31     }
32 }sam;
33 int head[maxn],sum;
34 struct edge {
35     int to,next;
36 }e[maxn];
37 void add(int u,int v) {e[sum].to=v;e[sum].next=head[u];head[u]=sum++;}
38 char s[maxn];
39 void dfs(int x) {
40     c[x]+=c[sam.link[x]];ans[sam.t[x]]+=c[x];
41     for(int i=head[x];i>=0;i=e[i].next) dfs(e[i].to);
42 }
43 int main() {
44     memset(head,-1,sizeof(head));
45     scanf("%d%d",&n,&k);
46     for(int i=1;i<=n;i++) {
47         scanf("%s",s+1);
48         int len=strlen(s+1);sam.last=1;
49         for(int j=1;j<=len;j++) sam.extend(s[j]-'a',i);
50     }
51     for(int i=2;i<=sam.cnt;i++)    {
52         add(sam.link[i],i);
53         if(sam.size[i]>=k) c[i]=sam.step[i]-sam.step[sam.link[i]];
54     }
55     dfs(1);
56     for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
57 }
58 /*
59 3 2
60 abaac
61 bba
62 bbacb
63 */
View Code

 

posted @ 2018-02-26 19:16  wls001  阅读(247)  评论(0编辑  收藏  举报