Bzoj3277 串

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 568  Solved: 233

Description

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

Input

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

Output

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

Sample Input


3 1
abc
a
ab

Sample Output

6 1 3

HINT

对于100%的数据,n,k,l<=100000

Source

 

广义后缀自动机

把所有串建成广义后缀自动机,开一个size数组记录每个结点被多少个串经过。

若一个结点x的size>=k,则它有maxlen[x]-maxlen[fa[x]](即right集合大小)个贡献,否则贡献为0

从自动机root开始DFS一遍,累计每个点的贡献。

对于每个串,用它在自动机上跑一遍,累计所有经过的点的贡献,即是答案。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<vector>
  7 #define LL long long
  8 using namespace std;
  9 const int mxn=200011;
 10 int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 14     return x*f;
 15 }
 16 struct edge{
 17     int v,nxt;
 18 }e[mxn<<1];
 19 int hd[mxn],mct=0;
 20 void add_edge(int u,int v){
 21     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;
 22     return;
 23 }
 24 vector<int>ve[mxn>>1];
 25 int n,K;
 26 int id;
 27 struct SAM{
 28     int t[mxn][26];
 29     int fa[mxn],mx[mxn];LL sz[mxn];
 30     int w[mxn],rk[mxn];
 31     int nxt[mxn];
 32     int S,last,cnt;
 33     void init(){S=last=cnt=1;return;}
 34     void add(int c){
 35 //      printf("add:%d\n",c);
 36         int np=++cnt,p=last;last=np;
 37         mx[np]=mx[p]+1;
 38         for(;p && !t[p][c];p=fa[p])t[p][c]=np;
 39         if(!p){fa[np]=S;}
 40         else{
 41             int q=t[p][c];
 42             if(mx[q]==mx[p]+1)fa[np]=q;
 43             else{
 44                 int nq=++cnt;mx[nq]=mx[p]+1;
 45                 memcpy(t[nq],t[q],sizeof t[q]);
 46                 sz[nq]=sz[q];nxt[nq]=nxt[q];
 47                 fa[nq]=fa[q];
 48                 fa[q]=fa[np]=nq;
 49                 for(;p && t[p][c]==q;p=fa[p])t[p][c]=nq;
 50             }
 51         }
 52         ve[id].push_back(np);
 53         while(np){
 54             if(nxt[np]!=id){++sz[np];nxt[np]=id;np=fa[np];}
 55             else break;
 56         }
 57         return;
 58     }
 59     void ST(){
 60         for(int i=1;i<=cnt;i++)++w[mx[i]];
 61         for(int i=1;i<=cnt;i++)w[i]+=w[i-1];
 62         for(int i=cnt;i;i--)rk[w[mx[i]]--]=i;
 63         for(int i=1;i<=cnt;i++){
 64             int r=rk[i];
 65             add_edge(fa[r],r);
 66             sz[r]=(sz[r]>=K)?mx[r]-mx[fa[r]]:0;
 67         }
 68         return;
 69     }
 70     void DFS(int u){
 71         sz[u]+=sz[fa[u]];
 72         for(int i=hd[u];i;i=e[i].nxt)
 73             DFS(e[i].v);
 74         return;
 75     }
 76 }sa;
 77 char s[mxn];
 78 int main(){
 79     int i,j;
 80     n=read();K=read();
 81     sa.init();
 82     for(i=1;i<=n;i++){
 83         scanf("%s",s+1);
 84         int len=strlen(s+1);
 85         id=i;
 86         for(j=1;j<=len;j++)sa.add(s[j]-'a');
 87         sa.last=sa.S;
 88     }
 89     sa.ST();
 90     sa.DFS(1);
 91     sa.sz[sa.S]=0;
 92     LL ans=0;
 93     for(i=1;i<=n;i++){
 94         ans=0;int ed=ve[i].size();
 95         for(j=0;j<ed;j++){
 96             ans+=sa.sz[ve[i][j]];
 97         }
 98         printf("%lld ",ans);
 99     }
100     return 0;
101 }
102 

 

posted @ 2017-05-25 11:41  SilverNebula  阅读(196)  评论(0编辑  收藏  举报
AmazingCounters.com