码迷,mamicode.com
首页 > 编程语言 > 详细

十、后缀数组

时间:2015-07-14 22:47:39      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:

模板:

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





版权声明:本文为博主原创文章,未经博主允许不得转载。

十、后缀数组

标签:

原文地址:http://blog.csdn.net/boyxiejunboy/article/details/46882405

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!