BZOJ3277 串

https://www.lydsy.com/JudgeOnline/problem.php?id=3277

把多个串插入广义后缀自动机中,建出parent树,在树上做set启发式合并,

记录下每一个前缀在不同串出现的次数,

再对每个串暴力匹配一遍,求出答案即可.

复杂度O(nlogn)

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<string>
  6 #include<set>
  7 #define rep(i,s,t) for(register int i=s;i<=t;++i)
  8 #define _rep(i,s,t) for(register int i=s;i>=t;--i)
  9 #define Rep(i,s,t) for(register int i=s;i<t;++i)
 10 using namespace std;
 11 namespace IO{
 12     #define gc getchar()
 13     #define pc(x) putchar(x)
 14     template<typename T>inline void read(T &x){
 15         x=0;int f=1;char ch=gc;
 16         while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;}
 17         while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc;
 18         x*=f;return;
 19     }
 20     template<typename T>inline void write(T x=0){
 21         T wr[51];wr[0]=0;
 22         if(x<0)pc('-'),x=-x;
 23         if(!x)pc(48);
 24         while(x)wr[++wr[0]]=x%10,x/=10;
 25         while(wr[0])pc(48+wr[wr[0]--]);
 26         return;
 27     }
 28 }
 29 using IO::read;
 30 using IO::write;
 31 const int N=2e5+11;
 32 typedef long long ll;
 33 int n,k,len;
 34 string S[N];
 35 struct SAM{
 36     int las,cnt,tot,ch[N][26],l[N],
 37         fa[N],c[N],pos[N],sz[N],
 38         nxt[N*6],lst[N],to[N*6];
 39     set<int>s[N];
 40     ll ans;
 41     SAM(){
 42         las=cnt=1;
 43     }
 44     inline void add(int c,int x){
 45         int np=++cnt,p=las;las=np,l[np]=l[p]+1,s[np].insert(x);
 46         for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
 47         if(!p)fa[np]=1;
 48         else{
 49             int q=ch[p][c];
 50             if(l[p]+1==l[q])
 51                 fa[np]=q;
 52             else{
 53                 int nq=++cnt;l[nq]=l[p]+1;
 54                 memcpy(ch[nq],ch[q],sizeof ch[q]);
 55                 fa[nq]=fa[q],fa[q]=fa[np]=nq;
 56                 for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
 57             }
 58         }
 59     }
 60     inline void merge(int x,int y){
 61         if(s[x].size()>s[y].size())
 62             swap(s[x],s[y]);
 63         set<int>::iterator it;
 64         for(it=s[x].begin();it!=s[x].end();++it)
 65             s[y].insert(*it);
 66         s[x].clear();
 67     }
 68     inline void adde(int x,int y){
 69         nxt[++tot]=lst[x],lst[x]=tot,to[tot]=y;
 70     }
 71     inline void dfs(int x){
 72         for(register int e=lst[x];e;e=nxt[e]){
 73             dfs(to[e]);
 74             merge(to[e],x);
 75         }
 76         sz[x]=s[x].size();
 77     }
 78     inline void solve(){
 79         rep(i,1,cnt)
 80             if(fa[i])
 81                 adde(fa[i],i);
 82         dfs(1);
 83         rep(i,1,n){
 84             len=S[i].length(),las=1,ans=0;
 85             Rep(j,0,len){
 86                 las=ch[las][S[i][j]-'a'];
 87                 for(;sz[las]<k;las=fa[las]);
 88                 ans+=l[las];
 89             }
 90             printf("%lld ",ans);
 91         }
 92         puts("");
 93     }
 94 }sam;
 95 int main(){
 96     scanf("%d%d",&n,&k);
 97     rep(i,1,n){
 98         cin>>S[i];
 99         len=S[i].length(),sam.las=1;
100         Rep(j,0,len)
101             sam.add(S[i][j]-'a',i);
102     }
103     if(k>n){
104         rep(i,1,n)
105             printf("0 ");
106         return 0;
107     }
108     sam.solve();
109     return 0;
110 }
code

 

posted @ 2018-05-05 22:19  Stump  阅读(163)  评论(0编辑  收藏  举报