首页 > 代码库 > 后缀数组
后缀数组
追随蔡大神的脚步,开始后缀数组的学习。
//时间不够不定时不定期完善
一、后缀数组的定义
模版1(远古写法)
var s:ansistring; n,tot:longint; c,x,y,rank,sa:array[0..1000]of longint;procedure first;var i:longint;begin readln(s); n:=length(s); for i:=1 to n do x[i]:=ord(s[i]); fillchar(c,sizeof(c),0); for i:=1 to n do inc(c[x[i]]); for i:=1 to 128 do inc(c[i],c[i-1]); for i:=1 to n do begin sa[c[x[i]]]:=i; dec(c[x[i]]); end; tot:=1; rank[sa[1]]:=1; for i:=2 to n do begin if x[sa[i]]<>x[sa[i-1]] then inc(tot); rank[sa[i]]:=tot; end;end;procedure calcsa;var i,p:longint;begin p:=1; while p<n do begin for i:=1 to n-p do y[i]:=rank[i+p]; for i:=n-p+1 to n do y[i]:=0; fillchar(c,sizeof(c),0); for i:=1 to n do inc(c[y[i]]); for i:=1 to n do inc(c[i],c[i-1]); for i:=1 to n do begin sa[c[y[i]]]:=i; dec(c[y[i]]); end; for i:=1 to n do x[i]:=rank[i]; fillchar(c,sizeof(c),0); for i:=1 to n do inc(c[x[i]]); for i:=1 to n do inc(c[i],c[i-1]); for i:=n downto 1 do begin y[sa[i]]:=c[x[sa[i]]]; dec(c[x[sa[i]]]); end; for i:=1 to n do sa[y[i]]:=i; tot:=1; rank[sa[1]]:=1; for i:=2 to n do begin if (x[sa[i]]<>x[sa[i-1]]) or (x[sa[i]+p]<>x[sa[i-1]+p]) then inc(tot); rank[sa[i]]:=tot; end; if tot=n then break; p:=p<<1; end; for i:=1 to n do sa[rank[i]]:=i; for i:=1 to n do write(sa[i],‘ ‘); writeln; for i:=1 to n do write(rank[i],‘ ‘);end;begin first; calcsa; readln; readln;end.
跪了论文后……
模版2
var s:ansistring; n,tot:longint; c,x,y,rank,sa:array[0..1000]of longint;procedure swap(var j,k:longint);var i:longint;begin i:=j; j:=k; k:=i;end;procedure qsort(l,r:longint);var i,j,mid:longint;begin i:=l; j:=r; mid:=x[(l+r) div 2]; repeat while x[i]<mid do inc(i); while x[j]>mid do dec(j); if i<=j then begin swap(x[i],x[j]); swap(y[i],y[j]); inc(i); dec(j); end; until i>j; if i<r then qsort(i,r); if l<j then qsort(l,j);end;procedure first;var i:longint;begin readln(s); n:=length(s); { //如果n太大用快排据说会快? for i:=1 to n do begin x[i]:=ord(s[i]); y[i]:=i; end; qsort(1,n); for i:=1 to n do sa[i]:=y[i]; tot:=1; rank[sa[1]]:=1; for i:=2 to n do begin if x[i]<>x[i-1] then inc(tot); rank[sa[i]]:=tot; end; } for i:=1 to n do x[i]:=ord(s[i]); fillchar(c,sizeof(c),0); for i:=1 to n do inc(c[x[i]]); for i:=1 to 128 do inc(c[i],c[i-1]); for i:=1 to n do begin sa[c[x[i]]]:=i; dec(c[x[i]]); end; tot:=1; rank[sa[1]]:=1; for i:=2 to n do begin if x[sa[i]]<>x[sa[i-1]] then inc(tot); rank[sa[i]]:=tot; end;end;procedure calcsa;var i,p,sum:longint;begin p:=1; while p<n do begin sum:=0; for i:=n-p+1 to n do begin inc(sum); y[sum]:=i; end; for i:=1 to n do if sa[i]>p then begin inc(sum); y[sum]:=sa[i]-p; if sum=n then break; end; for i:=1 to n do x[i]:=rank[y[i]]; fillchar(c,sizeof(c),0); for i:=1 to n do inc(c[x[i]]); for i:=1 to n do inc(c[i],c[i-1]); for i:=n downto 1 do begin sa[c[x[i]]]:=y[i]; dec(c[x[i]]); end; tot:=1; x[sa[1]]:=1; for i:=2 to n do begin if (rank[sa[i]]<>rank[sa[i-1]]) or (rank[sa[i]+p]<>rank[sa[i-1]+p]) then inc(tot); x[sa[i]]:=tot; end; for i:=1 to n do rank[i]:=x[i]; if tot=n then break; p:=p<<1; end; for i:=1 to n do sa[rank[i]]:=i; for i:=1 to n do write(sa[i],‘ ‘); writeln; for i:=1 to n do write(rank[i],‘ ‘);end;begin first; calcsa; readln; readln;end.
Staginner大神的博客讲的非常好……以及某个笔记(然后2B了两小时看了这个东西还得再半小时才搞出来了……蒟蒻果然是太弱了)
后缀数组
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。