【POJ2774&Ural1517】Long Long Message(后缀数组)

题意:求两个字符串的最长公共子串

n<=1000

思路:这是一道论文题

  1 var x,y,sa,rank,wc,wd,a,height:array[0..210000]of longint;
  2     n,l1,l2,i,ans,m,l,r:longint;
  3     ch:ansistring;
  4 
  5 procedure swap(var x,y:longint);
  6 var t:longint;
  7 begin
  8  t:=x; x:=y; y:=t;
  9 end;
 10 
 11 function max(x,y:longint):longint;
 12 begin
 13  if x>y then exit(x);
 14  exit(y);
 15 end;
 16 
 17 function cmp(a,b,l:longint):boolean;
 18 begin
 19  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
 20 end;
 21 
 22 procedure getsa(n:longint);
 23 var i,j,p:longint;
 24 begin
 25  for i:=0 to n-1 do
 26  begin
 27   x[i]:=a[i];
 28   inc(wc[a[i]]);
 29  end;
 30  for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 31  for i:=n-1 downto 0 do
 32  begin
 33   dec(wc[x[i]]);
 34   sa[wc[x[i]]]:=i;
 35  end;
 36  j:=1; p:=1;
 37  while p<n do
 38  begin
 39   p:=0;
 40   for i:=n-j to n-1 do
 41   begin
 42    y[p]:=i; inc(p);
 43   end;
 44   for i:=0 to n-1 do
 45    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
 46   for i:=0 to n-1 do wd[i]:=x[y[i]];
 47   for i:=0 to m-1 do wc[i]:=0;
 48   for i:=0 to n-1 do inc(wc[wd[i]]);
 49   for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 50   for i:=n-1 downto 0 do
 51   begin
 52    dec(wc[wd[i]]);
 53    sa[wc[wd[i]]]:=y[i];
 54   end;
 55   for i:=0 to n do swap(x[i],y[i]);
 56   p:=1; x[sa[0]]:=0;
 57   for i:=1 to n-1 do
 58    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
 59     else begin x[sa[i]]:=p; inc(p); end;
 60   j:=j*2;
 61   m:=p;
 62  end;
 63 end;
 64 
 65 procedure getheight(n:longint);
 66 var i,j,k:longint;
 67 begin
 68  for i:=1 to n do rank[sa[i]]:=i;
 69  k:=0;
 70  for i:=0 to n-1 do
 71  begin
 72   if k>0 then dec(k);
 73   j:=sa[rank[i]-1];
 74   while a[i+k]=a[j+k] do inc(k);
 75   height[rank[i]]:=k;
 76  end;
 77 end;
 78 
 79 begin
 80  assign(input,'poj2774.in'); reset(input);
 81  assign(output,'poj2774.out'); rewrite(output);
 82  readln(ch);
 83  l1:=length(ch);
 84  for i:=0 to l1-1 do a[i]:=ord(ch[i+1]);
 85  a[l1]:=1;
 86  readln(ch);
 87  l2:=length(ch);
 88  for i:=l1+1 to l1+l2 do a[i]:=ord(ch[i-l1]);
 89  n:=l1+l2+1; a[n]:=0; m:=300;
 90  getsa(n+1);
 91  getheight(n);
 92  inc(n);
 93  for i:=2 to n do
 94  begin
 95   l:=sa[i-1]+1; r:=sa[i]+1;
 96   if l>r then swap(l,r);
 97   if (l<=l1)and(r>=l1+2) then ans:=max(ans,height[i]);
 98  end;
 99 
100  writeln(ans);
101 
102  close(input);
103  close(output);
104 end.

 

posted on 2017-02-20 18:48  myx12345  阅读(144)  评论(0编辑  收藏  举报

导航