您的位置:首页 > 其它

十、后缀数组

2015-07-14 19:27 260 查看
模板:

1.快排:

var

rank,height,h:array [0..300000] of qword;

//rank[i]:i的后缀的排名;

//height[i]:lcp(s[a[i,2]...len],s[a[i-1,2]...len]);

//h[i]:lcp(s[i...len],s[a[rank[i]-1,2]...len]);

//h[i]>=h[i]-1;

a:array [1..300000,1..2] of qword;

f:array [1..300000] of boolean;

s:string;

i,j,m,n,k,mm:longint;

x:qword;

procedure cha(l,r:longint);

var

i,j:longint;

mid,t:qword;

begin

i:=l;

j:=r;

mid:=a[(l+r) div 2,1];

while i<=j do

begin

while a[i,1]<mid do inc(i);

while a[j,1]>mid do dec(j);

if (i<=j) then

begin

t:=a[i,1];

a[i,1]:=a[j,1];

a[j,1]:=t;

t:=a[i,2];

a[i,2]:=a[j,2];

a[j,2]:=t;

inc(i);

dec(j);

end;

end;

if j>l then cha(l,j);

if i<r then cha(i,r);

end;

begin

assign(input,'sss.in');

assign(output,'sss.out');

reset(input);

rewrite(output);

readln(s);

for i:=1 to length(s) do

begin

a[i,1]:=ord(s[i])-ord('a')+1;

a[i,2]:=i;

rank[i]:=a[i,1];

end;

m:=1;

while n<>length(s) do

begin

n:=0;

if m<>0 then

for i:=1 to length(s) do

begin

x:=rank[i]*1000000;

x:=x+rank[i+m];

a[i,1]:=x;

a[i,2]:=i;

end;

cha(1,length(s));

n:=1;

rank[a[1,2]]:=1;

for i:=2 to length(s) do

begin

if a[i,1]<>a[i-1,1] then

inc(n);

rank[a[i,2]]:=n;

end;

m:=m*2;

end;

for i:=1 to length(s) do

write(a[i,2],' ');

writeln;

j:=0;

for i:=1 to length(s) do

begin

if j>0 then dec(j);

while (rank[i]-1<>0) and (s[i+j]=s[a[rank[i]-1,2]+j]) do inc(j);

h[i]:=j;

height[rank[i]]:=j;

end;

for i:=1 to length(s) do

write(height[i],' ');

writeln;

for i:=1 to length(s) do

write(h[i],' ');

writeln;

close(input);

close(output);

end.

2.桶排

var

rank,sa,lis,a:array [1..10000] of longint;

f:array [1..10000] of boolean;

s:string;

i,j,m,n,k:longint;

begin

readln(s);

m:=1;

for i:=1 to length(s) do

rank[i]:=ord(s[i])-ord('a')+1;

while n<>length(s) do

begin

n:=0;

for i:=1 to length(s) do

a[i]:=rank[i]*100+rank[i+m];

fillchar(f,sizeof(f),false);

for i:=1 to length(s) do

begin

if not f[a[i]] then

begin

inc(n);

f[a[i]]:=true;

end;

end;

k:=0;

for i:=1 to 2626 do

if f[i] then

begin

inc(k);

lis[i]:=k;

end;

for i:=1 to length(s) do

rank[i]:=lis[a[i]];

m:=m*2;

end;

for i:=1 to length(s) do

write(rank[i],' ');

writeln;

end.

倍增算法解释:

样例1:

sa:1 2 3 5 1 1 2 4

第一次排序rank:102 203 305 501 101 102 204 400

sa:2 3 5 7 1 2 4 6

第二次排序rank:205 307 501 702 104 206 400 600
sa:2 4 6 8 1 4 5 7

样例2:
sa:1 1 2 1 1 1 1 2
第一次排序rank:101 102 201 101 101 101 102 200
sa:1 2 4 1 1 1 2 3
第二次排序rank:104 201 401 101 102 103 200 300
sa:4 6 8 1 2 3 5 7
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: