ZOJ2006 (后缀自动机)
求一个字符串的最小表示法。
将字符串S倍长,从根走length(s)步所走路径即为最小表示法。
记所到达位置为x,则这个最小表示法的起点为a[x]-len(s)+1
1 const maxn=20008; 2 var T:longint; 3 nt:array[0..maxn,'a'..'z'] of longint; 4 a,f:array[0..maxn] of longint; 5 sum,last:longint; 6 s:ansistring; 7 procedure Sam_init; 8 begin 9 fillchar(nt,sizeof(nt),255); 10 fillchar(a,sizeof(a),0); 11 fillchar(f,sizeof(f),255); 12 sum:=0; last:=0; 13 end; 14 procedure Sam_ins(i:longint); 15 var p,q,np,nq:longint; 16 ch:char; 17 begin 18 ch:=s[i]; 19 p:=last; inc(sum); np:=sum; a[np]:=a[p]+1; last:=np; 20 while (p<>-1) and (nt[p][ch]=-1) do begin nt[p][ch]:=np; p:=f[p]; end; 21 if p=-1 then f[np]:=0 else 22 begin 23 q:=nt[p][ch]; 24 if a[p]+1=a[q] then f[np]:=q else 25 begin 26 inc(sum); nq:=sum; a[nq]:=a[p]+1; 27 nt[nq]:=nt[q]; f[nq]:=f[q]; 28 f[q]:=nq; f[np]:=nq; 29 while (p<>-1) and (nt[p][ch]=q) do begin nt[p][ch]:=nq; p:=f[p]; end; 30 end; 31 end; 32 end; 33 procedure dfs(now,len:longint); 34 var ch:char; 35 begin 36 if len=0 then 37 begin 38 writeln(a[now]-length(s) div 2+1); 39 exit; 40 end; 41 for ch:='a' to 'z' do 42 if nt[now][ch]<>-1 then 43 begin 44 dfs(nt[now][ch],len-1); 45 exit; 46 end; 47 end; 48 procedure main; 49 var i:longint; 50 begin 51 readln(s); 52 s:=s+s; 53 Sam_init; 54 for i:=1 to length(s) do Sam_ins(i); 55 dfs(0,length(s) div 2); 56 end; 57 begin 58 readln(T); 59 while T>0 do begin dec(T); main; end; 60 end.