您的位置:首页 > 其它

ZOJ2006 (后缀自动机)

2015-06-10 16:16 302 查看
求一个字符串的最小表示法。

将字符串S倍长,从根走length(s)步所走路径即为最小表示法。

记所到达位置为x,则这个最小表示法的起点为a[x]-len(s)+1

const maxn=20008;
var T:longint;
nt:array[0..maxn,'a'..'z'] of longint;
a,f:array[0..maxn] of longint;
sum,last:longint;
s:ansistring;
procedure Sam_init;
begin
fillchar(nt,sizeof(nt),255);
fillchar(a,sizeof(a),0);
fillchar(f,sizeof(f),255);
sum:=0; last:=0;
end;
procedure Sam_ins(i:longint);
var p,q,np,nq:longint;
ch:char;
begin
ch:=s[i];
p:=last; inc(sum); np:=sum; a[np]:=a[p]+1; last:=np;
while (p<>-1) and (nt[p][ch]=-1) do begin nt[p][ch]:=np; p:=f[p]; end;
if p=-1 then f[np]:=0 else
begin
q:=nt[p][ch];
if a[p]+1=a[q] then f[np]:=q else
begin
inc(sum); nq:=sum; a[nq]:=a[p]+1;
nt[nq]:=nt[q]; f[nq]:=f[q];
f[q]:=nq; f[np]:=nq;
while (p<>-1) and (nt[p][ch]=q) do begin nt[p][ch]:=nq; p:=f[p]; end;
end;
end;
end;
procedure dfs(now,len:longint);
var ch:char;
begin
if len=0 then
begin
writeln(a[now]-length(s) div 2+1);
exit;
end;
for ch:='a' to 'z' do
if nt[now][ch]<>-1 then
begin
dfs(nt[now][ch],len-1);
exit;
end;
end;
procedure main;
var i:longint;
begin
readln(s);
s:=s+s;
Sam_init;
for i:=1 to length(s) do Sam_ins(i);
dfs(0,length(s) div 2);
end;
begin
readln(T);
while T>0 do begin dec(T); main; end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: