这里学习AC自动机
其实对KMP和trie掌握好了之后很容易扩展成AC自动机的
这里运用了一个性质
由失配指针反向可以建成一棵fail树
x串在y串中的出现的次数即为在fail树上以x结尾节点为根的子树中有多少个节点属于y串,这很好理解
而推广到这题,在文章中出现的次数即为单词结尾节点为根的子树的规模
注意这道题有相同的单词
当初这题我是用后缀数组做的O(LlogL)
而自动机复杂度为O(L),快了很多
1 type node=record 2 po,next:longint; 3 end; 4 5 var e:array[0..1000010] of node; 6 trie:array[0..1000010,'a'..'z'] of longint; 7 q,f,p,w:array[0..1000010] of longint; 8 v:array[0..210] of longint; 9 t,i,j,k,n,l,len:longint; 10 s:ansistring; 11 12 procedure add(x,y:longint); 13 begin 14 inc(len); 15 e[len].po:=y; 16 e[len].next:=p[x]; 17 p[x]:=len; 18 end; 19 20 procedure bfs; 21 var x,y,h,r,j:longint; 22 c:char; 23 begin 24 h:=1; 25 r:=0; 26 for c:='a' to 'z' do 27 if trie[0,c]>0 then 28 begin 29 add(0,trie[0,c]); 30 inc(r); 31 q[r]:=trie[0,c]; 32 end; 33 34 while h<=r do 35 begin 36 x:=q[h]; 37 for c:='a' to 'z' do 38 if trie[x,c]>0 then 39 begin 40 y:=trie[x,c]; 41 inc(r); 42 q[r]:=y; 43 j:=f[x]; 44 while (j>0) and (trie[j,c]=0) do j:=f[j]; 45 f[y]:=trie[j,c]; 46 add(trie[j,c],y); 47 end; 48 inc(h); 49 end; 50 end; 51 52 procedure dfs(x:longint); 53 var i,y:longint; 54 begin 55 i:=p[x]; 56 while i<>0 do 57 begin 58 y:=e[i].po; 59 dfs(y); 60 w[x]:=w[y]+w[x]; 61 i:=e[i].next; 62 end; 63 end; 64 65 begin 66 readln(n); 67 for i:=1 to n do 68 begin 69 readln(s); 70 j:=0; 71 l:=length(s); 72 for k:=1 to l do 73 begin 74 if trie[j,s[k]]=0 then 75 begin 76 inc(t); 77 trie[j,s[k]]:=t; 78 end; 79 j:=trie[j,s[k]]; 80 inc(w[j]); 81 end; 82 v[i]:=j; 83 end; 84 bfs; 85 dfs(0); 86 for i:=1 to n do 87 writeln(w[v[i]]); 88 end.
1 var h,rank,x,y,sum,sa:array[0..1010000] of longint; 2 f:array[0..1010000,0..30] of longint; 3 where,len,d:array[0..500] of longint; 4 now, k,ans,i,j,p,n,m,t,l,r:longint; 5 s,cc:ansistring; 6 function min(a,b:longint):longint; 7 begin 8 if a>b then exit(b) else exit(a); 9 end; 10 11 function lcp(a,b:longint):longint; 12 var k:longint; 13 begin 14 k:=trunc(ln(b-a+1)/ln(2)); 15 exit(min(f[a,k],f[b-d[k]+1,k])); 16 end; 17 18 begin 19 readln(t); 20 for i:=1 to t do 21 begin 22 readln(cc); 23 where[i]:=length(s)+1; 24 len[i]:=length(cc); 25 s:=s+cc; 26 if i<>t then s:=s+' '; 27 end; 28 { for i:=1 to t do 29 writeln(where[i],' ',len[i]);} 30 n:=length(s); 31 for i:=1 to n do 32 begin 33 y[i]:=ord(s[i]); 34 inc(sum[y[i]]); 35 end; 36 m:=130; 37 for i:=2 to 130 do 38 inc(sum[i],sum[i-1]); 39 for i:=1 to n do 40 begin 41 sa[sum[y[i]]]:=i; 42 dec(sum[y[i]]); 43 end; 44 p:=1; 45 rank[sa[1]]:=1; 46 for i:=2 to n do 47 begin 48 if y[sa[i]]<>y[sa[i-1]] then inc(p); 49 rank[sa[i]]:=p; 50 end; 51 m:=p; 52 j:=1; 53 while m<n do 54 begin 55 y:=rank; 56 fillchar(sum,sizeof(sum),0); 57 p:=0; 58 for i:=n-j+1 to n do 59 begin 60 inc(p); 61 x[p]:=i; 62 end; 63 for i:=1 to n do 64 if sa[i]>j then 65 begin 66 inc(p); 67 x[p]:=sa[i]-j; 68 end; 69 for i:=1 to n do 70 begin 71 rank[i]:=y[x[i]]; 72 inc(sum[rank[i]]); 73 end; 74 for i:=2 to m do 75 inc(sum[i],sum[i-1]); 76 for i:=n downto 1 do 77 begin 78 sa[sum[rank[i]]]:=x[i]; 79 dec(sum[rank[i]]); 80 end; 81 p:=1; 82 rank[sa[1]]:=1; 83 for i:=2 to n do 84 begin 85 if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p); 86 rank[sa[i]]:=p; 87 end; 88 j:=j shl 1; 89 m:=p; 90 end; 91 h[1]:=0; 92 p:=0; 93 for i:=1 to n do 94 begin 95 if rank[i]=1 then continue; 96 j:=sa[rank[i]-1]; 97 while s[i+p]=s[j+p] do inc(p); 98 h[rank[i]]:=p; 99 if p>0 then dec(p); 100 end; 101 k:=trunc(ln(n)/ln(2)); 102 d[0]:=1; 103 for i:=1 to k do 104 d[i]:=d[i-1]*2; 105 for i:=1 to n do 106 f[i,0]:=h[i]; 107 for j:=1 to k do 108 for i:=1 to n do 109 if i+d[j]-1<=n then 110 begin 111 f[i,j]:=min(f[i,j-1],f[i+d[j-1],j-1]); 112 end 113 else break; 114 for i:=1 to t do 115 begin 116 ans:=1; 117 k:=-1; 118 l:=1; 119 now:=rank[where[i]]; 120 r:=now-1; 121 while l<=r do 122 begin 123 m:=(l+r) shr 1; 124 if lcp(m+1,now)>=len[i] then 125 begin 126 k:=m; 127 r:=m-1 128 end 129 else l:=m+1; 130 end; 131 if k<>-1 then ans:=ans+now-k; 132 l:=now+1; 133 k:=-1; 134 r:=n; 135 while l<=r do 136 begin 137 m:=(l+r) shr 1; 138 if lcp(now+1,m)>=len[i] then 139 begin 140 k:=m; 141 l:=m+1; 142 end 143 else r:=m-1; 144 end; 145 if k<>-1 then ans:=ans+k-now; 146 writeln(ans); 147 end; 148 end.