您的位置:首页 > 其它

后缀自动机

2015-06-10 08:44 232 查看
http://blog.sina.com.cn/s/blog_7812e98601012cim.html //后缀自动机建立的详细介绍
http://www.tuicool.com/articles/Mjuu2y //后缀自动机学习指南(习题列表)

const maxn=10008;
var    a,f,rig:array[0..maxn] of longint;
nt:array[0..maxn,'a'..'z'] of longint;
last,sum,i:longint;
s:ansistring;

eg:array[0..maxn*2] of record nt,v:longint; end;
lt:array[0..maxn] of longint;
el:longint;

procedure SAM_init;
begin
fillchar(f,sizeof(f),255);
fillchar(nt,sizeof(nt),255);
fillchar(a,sizeof(a),0);
last:=0; sum:=0;
end;

procedure SAM_ins(ch:char);
var next,p,np,q,nq:longint;
begin
//next:=nt[last][ch]; 添加多个串使用
//if (next<>-1) and (f[last+1]<>f[next]) then begin last:=next; exit; end;
inc(sum); p:=last; np:=sum; a[np]:=a[p]+1; last:=np; rig[np]:=1;
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 SAM_visit; //遍历所有后缀
var x:longint;
v:array[0..maxn] of boolean;
procedure dfs(now:longint; t:string);
var c:char;
begin
if v[now] then writeln(t);
for c:='a' to 'z' do
if nt[now][c]<>-1 then
dfs(nt[now][c],t+c);
end;
begin
x:=last;
while x<>0 do begin v[x]:=true; x:=f[x]; end;
dfs(0,'');
end;

procedure SAM_visit1;//遍历所有子串 并统计次数
procedure dfs(now:longint; t:string);
var c:char;
begin
if now<>0 then writeln(t,'  ',rig[now]);
for c:='a' to 'z' do
if nt[now][c]<>-1 then
dfs(nt[now][c],t+c);
end;
begin
dfs(0,'');
end;

function SAM_calc:longint; //本质不同的串
var i,cnt:longint;
begin
cnt:=0;
for i:=1 to sum do cnt:=cnt+a[i]-a[f[i]];
exit(cnt);
end;

procedure SAM_rig;
procedure dfs(u:longint);
var i:longint;
begin
i:=lt[u];
while i<>0 do
begin
dfs(eg[i].v);
rig[u]:=rig[u]+rig[eg[i].v];
i:=eg[i].nt;
end;
end;
procedure add(u,v:longint);
begin
inc(el);
eg[el].v:=v;
eg[el].nt:=lt[u];
lt[u]:=el;
end;
begin
el:=0;
fillchar(lt,sizeof(lt),0);
for i:=1 to sum do add(f[i],i);
dfs(0);
end;

begin
SAM_init;
readln(s);
for i:=1 to length(s) do SAM_ins(s[i]);
SAM_rig;
SAM_visit1;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: