1. 程式人生 > >codeforces 204E. Little Elephant and Strings(廣義字尾自動機,Parent樹)

codeforces 204E. Little Elephant and Strings(廣義字尾自動機,Parent樹)

傳送門在這裡。

大意:

  給一堆字串,詢問每個字串有多少子串在所有字串中出現K次以上。

解題思路:

  這種子串問題一定要見字尾自動機Parent樹Dfs序統計出現次數都是套路了吧。

這道題統計子串個數,那麼可以發現,若一個節點所對應的子串出現了K次,那麼其貢獻就是len,不需要考慮重複。

因為即使出現重複也是在兩個位置。

那麼只需統計以每個點結束的子串就好了。

之前的Dfs序就很套路了。

只需再跑一遍字串,更新答案就好了。

程式碼:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4
const int N=400000; 5 struct sant{ 6 int tranc[26]; 7 int len; 8 int pre; 9 }s[N]; 10 struct pnt{ 11 int hd; 12 int ind; 13 int oud; 14 int col; 15 int ans; 16 }p[N]; 17 struct ent{ 18 int twd; 19 int lst; 20 }e[N]; 21 struct int_2{
22 int l; 23 int r; 24 int no; 25 }d[N]; 26 int n,k; 27 int siz; 28 int dfn; 29 int cnt; 30 int fin; 31 char tmp[N]; 32 int ll[N],rr[N]; 33 int col[N]; 34 int lst[N]; 35 int line[N]; 36 int str[N]; 37 int lowbit(int x) 38 { 39 return x&(-x); 40 }
41 void update(int pos,int x) 42 { 43 while(pos&&pos<=dfn) 44 { 45 line[pos]+=x; 46 pos+=lowbit(pos); 47 } 48 return ; 49 } 50 int query(int pos) 51 { 52 int ans=0; 53 while(pos) 54 { 55 ans+=line[pos]; 56 pos-=lowbit(pos); 57 } 58 return ans; 59 } 60 bool cmp(int_2 x,int_2 y) 61 { 62 return x.r<y.r; 63 } 64 void ade(int f,int t) 65 { 66 cnt++; 67 e[cnt].twd=t; 68 e[cnt].lst=p[f].hd; 69 p[f].hd=cnt; 70 return ; 71 } 72 void Insert(int c,int pl) 73 { 74 int nwp,nwq,lsp,lsq; 75 nwp=++siz; 76 s[nwp].len=s[fin].len+1; 77 p[nwp].col=pl; 78 for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre) 79 s[lsp].tranc[c]=nwp; 80 if(!lsp) 81 s[nwp].pre=1; 82 else{ 83 lsq=s[lsp].tranc[c]; 84 if(s[lsq].len==s[lsp].len+1) 85 s[nwp].pre=lsq; 86 else{ 87 nwq=++siz; 88 s[nwq]=s[lsq]; 89 s[nwq].len=s[lsp].len+1; 90 s[lsq].pre=s[nwp].pre=nwq; 91 while(s[lsp].tranc[c]==lsq) 92 { 93 s[lsp].tranc[c]=nwq; 94 lsp=s[lsp].pre; 95 } 96 } 97 } 98 fin=nwp; 99 } 100 void Dfs(int x) 101 { 102 p[x].ind=++dfn; 103 col[dfn]=p[x].col; 104 for(int i=p[x].hd;i;i=e[i].lst) 105 { 106 int to=e[i].twd; 107 Dfs(to); 108 } 109 p[x].oud=++dfn; 110 col[dfn]=p[x].col; 111 } 112 int main() 113 { 114 scanf("%d%d",&n,&k); 115 if(k>n) 116 { 117 for(int i=1;i<=n;i++) 118 printf("%d ",0); 119 return 0; 120 } 121 fin=++siz; 122 for(int i=1;i<=n;i++) 123 { 124 ll[i]=rr[i-1]+1; 125 rr[i]=rr[i-1]; 126 fin=1; 127 scanf("%s",tmp); 128 int len=strlen(tmp); 129 for(int j=0;j<len;j++) 130 str[++rr[i]]=tmp[j]-'a'; 131 for(int j=ll[i];j<=rr[i];j++) 132 { 133 Insert(str[j],i); 134 } 135 } 136 137 for(int i=2;i<=siz;i++) 138 ade(s[i].pre,i); 139 Dfs(1); 140 for(int i=1;i<=siz;i++) 141 d[i]=(int_2){p[i].ind,p[i].oud,i}; 142 std::sort(d+1,d+siz+1,cmp); 143 int r=1; 144 for(int i=1;i<=siz;i++) 145 { 146 while(r<=d[i].r) 147 { 148 if(!col[r]) 149 { 150 r++; 151 continue; 152 } 153 if(lst[col[r]]) 154 update(lst[col[r]],-1); 155 update(r,1); 156 lst[col[r]]=r; 157 r++; 158 } 159 r--; 160 p[d[i].no].ans=query(d[i].r)-query(d[i].l-1); 161 } 162 for(int i=1;i<=n;i++) 163 { 164 long long int ans=0; 165 int root=1; 166 for(int j=ll[i];j<=rr[i];j++) 167 { 168 root=s[root].tranc[str[j]]; 169 while(p[root].ans<k) 170 root=s[root].pre; 171 ans+=(long long)s[root].len; 172 } 173 printf("%I64d ",ans); 174 } 175 puts(""); 176 return 0; 177 }