首页 > 代码库 > 【SPOJ694&705】Distinct Substrings(后缀数组)

【SPOJ694&705】Distinct Substrings(后缀数组)

题意:求一个字符串的不相同的子串个数

n<=1000

思路:这是一道论文题

技术分享

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

 

【SPOJ694&705】Distinct Substrings(后缀数组)