以前不会想,也不会写。现在会写了,也大概想明白了。后缀数组,真是个麻烦的东西。

题目大意如下:给定一个长度在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.