POJ2774 Long Long Message——后缀数组——pku2774

参考罗穗骞神牛论文中求公共子串例题。

将两个字符串合并为一个,中间加上一个没有出现过的字符,我加上的是‘}’

然后求出height数组,并判断该height数组是否合法,如果合法就采用它来更新答案。

也是后缀数组的模板题吧。

代码:

Program poj2774;//By_Thispoet

Const

	maxn=200005;

Var

	i,j,k,m,n,p,q,sum,ans			:Longint;

	rank,sa,x,y,tmp,height			:Array[0..maxn]of Longint;

	st								:Array[0..maxn]of Char;

	pre,data						:Array[0..maxn]of Longint;

	link,last						:Array[0..maxn]of Longint;



Function Max(i,j:Longint):Longint;

begin

	if i>j then exit(i);exit(j);

end;





Procedure Sort();

begin



	k:=0;

	fillchar(link,sizeof(link),0);

	for i:=n downto 1 do 

		begin

			inc(k);pre[k]:=link[y[i]];

			link[y[i]]:=k;data[k]:=i;

		end;

	k:=0;

	for i:=0 to Max(n,30) do

		begin

			j:=link[i];

			while j<>0 do 

				begin

					inc(k);tmp[k]:=data[j];

					j:=pre[j];

				end;

		end;

	k:=0;

	fillchar(link,sizeof(link),0);

	for i:=n downto 1 do

		begin

			inc(k);pre[k]:=link[x[tmp[i]]];

			link[x[tmp[i]]]:=k;data[k]:=tmp[i];

		end;

	k:=0;

	for i:=0 to Max(n,30) do 

		begin

			j:=link[i];

			while j<>0 do 

				begin

					inc(k);tmp[k]:=data[j];

					j:=pre[j];

				end;

		end;

	for i:=1 to n do 

		begin

			sa[i]:=tmp[i];

			x[i]:=rank[sa[i]];

			y[i]:=rank[sa[i]+q];

		end;

	

end;





Function Check(i:Longint):Boolean;

begin

	if (x[i]<>x[i-1])or(y[i]<>y[i-1])then exit(true);

	exit(false);

end;





Function Judge(i:Longint):Boolean;

begin

	if (sa[i]>p)and(sa[i-1]>p)then exit(false);

	if (sa[i]<=p)and(sa[i-1]<=p)then exit(false);

	exit(true);

end;





BEGIN



	n:=0;

	while not eoln do

		begin

			inc(n);read(st[n]);

		end;

	p:=n;

	inc(n);st[n]:=chr(123);

	readln;

	while not eoln do

		begin

			inc(n);read(st[n]);

		end;



	for i:=1 to n do rank[i]:=ord(st[i])-96;

	q:=1;

	while q<=n-1 do

		begin

			for i:=1 to n do x[i]:=rank[i];

			for i:=1 to n do y[i]:=rank[i+q];

			Sort();

			rank[sa[1]]:=1;

			sum:=1;

			for i:=2 to n do

				begin

					if check(i) then inc(sum);

					rank[sa[i]]:=sum;

				end;

			if sum=n then break;

			q:=q<<1;

		end;



	fillchar(height,sizeof(height),0);

	while st[1+height[rank[1]]]=st[sa[rank[1]-1]+height[rank[1]]] do inc(height[rank[1]]);

	for i:=2 to n do

		begin

			height[rank[i]]:=Max(height[rank[i-1]]-1,0);

			while st[i+height[rank[i]]]=st[sa[rank[i]-1]+height[rank[i]]] do inc(height[rank[i]]);

		end;



	for i:=2 to n do

		if judge(i) then ans:=Max(ans,height[i]);



	writeln(ans);



END.

你可能感兴趣的:(message)