以前不会想,也不会写。现在会写了,也大概想明白了。后缀数组,真是个麻烦的东西。
题目大意如下:给定一个长度在5000以内的字符串,求出出现过两次或两次以上的最长字串(保证唯一解)。
不多说了,裸的后缀数组:
Program Suffix;//By_Thispoet Const maxn=10000; Var i,j,k,m,n,p,q,ans,pos,sum :Longint; rank,sa,a,x,y :Array[1..maxn]of Longint; st :Ansistring; Procedure Qsort(l,r:Longint); var i,j,k,p,temp:Longint; begin i:=l;j:=r;k:=x[(i+j)>>1];p:=y[(i+j)>>1]; repeat while (x[i]<k)or((x[i]=k)and(y[i]<p)) do inc(i); while (x[j]>k)or((x[j]=k)and(y[j]>p)) do dec(j); if i<=j then begin temp:=x[i];x[i]:=x[j];x[j]:=temp; temp:=y[i];y[i]:=y[j];y[j]:=temp; temp:=sa[i];sa[i]:=sa[j];sa[j]:=temp; inc(i);dec(j); end; until i>j; if i<r then Qsort(i,r); if l<j then Qsort(l,j); end; BEGIN readln(st); n:=length(st); p:=1; for i:=1 to n do rank[i]:=ord(st[i])-64; while p<=n-1 do begin for i:=1 to n do x[i]:=rank[i]; for i:=1 to n do y[i]:=rank[i+p]; for i:=1 to n do sa[i]:=i; Qsort(1,n); sum:=1; rank[sa[1]]:=1; for i:=2 to n do begin if (x[i]<>x[i-1])or(y[i]<>y[i-1]) then inc(sum); rank[sa[i]]:=sum; end; if sum=n then break; p:=p << 1; end; for i:=2 to n do begin p:=sa[i];q:=sa[i-1]; j:=0; while (p<=n)and(q<=n)and(st[p]=st[q]) do begin inc(j); inc(p);inc(q); end; if j>ans then begin ans:=j; pos:=p-1; end; end; writeln(ans); for i:=pos-ans+1 to pos do write(st[i]); writeln; END.