题意:求一个字符串的不重叠最长相同变化的子串
n<=20000
思路:这是一道论文题
我们将原串两两之间作差,可以发现所求的相同变化的子串作出的差相同
问题就转化成了不重叠的最长重复子串
显然答案有二分性,二分答案,将问题转化为是否存在长度为k的相同子串
将后缀分成连续的若干组,每组相邻的height都不小于k
有希望满足条件的两个后缀一定在同一组
只要判断某组中的sa最大与最小值之差是否不小于k即可
有一组满足则k满足
1 var a,b,wc,wd,x,y,height,sa,rank:array[0..100000]of longint; 2 n,i,l,r,mid,last,m:longint; 3 4 function cmp(a,b,l:longint):boolean; 5 begin 6 exit((y[a]=y[b])and(y[a+l]=y[b+l])); 7 end; 8 9 procedure swap(var x,y:longint); 10 var t:longint; 11 begin 12 t:=x; x:=y; y:=t; 13 end; 14 15 procedure getsa(n:longint); 16 var i,j,p:longint; 17 begin 18 for i:=0 to n-1 do 19 begin 20 x[i]:=a[i]; 21 inc(wc[a[i]]); 22 end; 23 for i:=1 to m do wc[i]:=wc[i-1]+wc[i]; 24 for i:=n-1 downto 0 do 25 begin 26 dec(wc[x[i]]); 27 sa[wc[x[i]]]:=i; 28 end; 29 j:=1; p:=1; 30 while p<n do 31 begin 32 p:=0; 33 for i:=n-j to n-1 do 34 begin 35 y[p]:=i; inc(p); 36 end; 37 for i:=0 to n-1 do 38 if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end; 39 for i:=0 to n-1 do wd[i]:=x[y[i]]; 40 for i:=0 to m do wc[i]:=0; 41 for i:=0 to n-1 do inc(wc[wd[i]]); 42 for i:=1 to m do wc[i]:=wc[i-1]+wc[i]; 43 for i:=n-1 downto 0 do 44 begin 45 dec(wc[wd[i]]); 46 sa[wc[wd[i]]]:=y[i]; 47 end; 48 for i:=0 to n do swap(x[i],y[i]); 49 p:=1; x[sa[0]]:=0; 50 for i:=1 to n-1 do 51 begin 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 end; 55 j:=j*2; 56 m:=p; 57 end; 58 end; 59 60 procedure getheight(n:longint); 61 var i,j,k:longint; 62 begin 63 k:=0; 64 for i:=1 to n do rank[sa[i]]:=i; 65 for i:=0 to n-1 do 66 begin 67 if k>0 then dec(k); 68 j:=sa[rank[i]-1]; 69 while a[i+k]=a[j+k] do inc(k); 70 height[rank[i]]:=k; 71 end; 72 end; 73 74 function min(x,y:longint):longint; 75 begin 76 if x<y then exit(x); 77 exit(y); 78 end; 79 80 function max(x,y:longint):longint; 81 begin 82 if x>y then exit(x); 83 exit(y); 84 end; 85 86 function isok(x:longint):boolean; 87 var l,r,i:longint; 88 begin 89 l:=sa[0]; r:=sa[0]; 90 for i:=1 to n-1 do 91 if height[i]<x then 92 begin 93 l:=sa[i]; r:=sa[i]; 94 end 95 else 96 begin 97 l:=min(l,sa[i]); 98 r:=max(r,sa[i]); 99 if r-l>=x then exit(true); 100 end; 101 exit(false); 102 end; 103 104 begin 105 assign(input,'poj1743.in'); reset(input); 106 assign(output,'poj1743.out'); rewrite(output); 107 while not eof do 108 begin 109 fillchar(a,sizeof(a),0); 110 fillchar(b,sizeof(b),0); 111 fillchar(sa,sizeof(sa),0); 112 fillchar(rank,sizeof(rank),0); 113 fillchar(x,sizeof(x),0); 114 fillchar(y,sizeof(y),0); 115 fillchar(height,sizeof(height),0); 116 fillchar(wc,sizeof(wc),0); 117 fillchar(wd,sizeof(wd),0); 118 readln(n); 119 if n=0 then break; 120 for i:=0 to n-1 do read(b[i]); 121 dec(n); 122 for i:=0 to n-1 do a[i]:=b[i+1]-b[i]+100; 123 a[n]:=0; m:=300; 124 getsa(n+1); 125 getheight(n); 126 l:=4; r:=(n-1) div 2; last:=0; 127 while l<=r do 128 begin 129 mid:=(l+r)>>1; 130 if isok(mid) then begin last:=mid; l:=mid+1; end 131 else r:=mid-1; 132 end; 133 if last<4 then writeln(0) 134 else writeln(last+1); 135 // for i:=1 to n do write(sa[i]+1,' '); 136 // writeln; 137 // for i:=0 to n do writeln(height[i]); 138 139 end; 140 141 close(input); 142 close(output); 143 end.