1. 程式人生 > >[BZOJ3172][TJOI2013]單詞 AC自動機

[BZOJ3172][TJOI2013]單詞 AC自動機

pos sin algo cstring n) -s 丟失 oid 一個

題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=3172

對這$n$個串建立AC自動機,求每個串的出現次數。

我們在建立時對每一個經過的節點sum++,然後在fail樹上從葉子節點不斷向上更新,因為父親節點代表的是孩子節點的一個後綴,所以孩子出現過的父親一定出現過,而fail指針的不遺漏性保證了答案不會丟失。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int
N,ch[1000010][26],fail[1000010],cnt=0; 6 int sum[1000010],pos[1000010]; 7 char tmp[1000010]; 8 int Insert(char *s){ 9 int now=0; 10 for(int i=0;s[i];i++){ 11 int idx=s[i]-a; 12 if(!ch[now][idx]) ch[now][idx]=++cnt; 13 now=ch[now][idx]; 14 sum[now]++; 15 } 16 return
now; 17 } 18 int q[1000010]; 19 void Setfail(){ 20 q[1]=0; 21 int head=1,tail=1; 22 while(head<=tail){ 23 int now=q[head]; 24 for(int i=0;i<26;i++){ 25 if(ch[now][i]){ 26 q[++tail]=ch[now][i]; 27 fail[ch[now][i]]=now?ch[fail[now]][i]:0
; 28 } 29 else ch[now][i]=ch[fail[now]][i]; 30 } 31 head++; 32 } 33 for(int i=tail;i>=1;i--) sum[fail[q[i]]]+=sum[q[i]]; 34 } 35 int main(){ 36 scanf("%d",&N); 37 for(int i=1;i<=N;i++){ 38 scanf("%s",tmp); 39 pos[i]=Insert(tmp); 40 } 41 Setfail(); 42 for(int i=1;i<=N;i++) printf("%d\n",sum[pos[i]]); 43 return 0; 44 }

[BZOJ3172][TJOI2013]單詞 AC自動機