求重复k次的最长重复子串,解法见罗穗骞大神的后缀数组论文
1 const maxn=100419; 2 3 var 4 x,y,rank,sa,h,s,num,c:array[0..maxn] of longint; 5 n,time:longint; 6 7 function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; 8 function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; 9 procedure make; 10 var i,j,p,tot:longint; 11 begin 12 p:=1; 13 while p<n do 14 begin 15 fillchar(c,sizeof(c),0); 16 for i:= 1 to n-p do y[i]:=rank[i+p]; 17 for i:= n-p+1 to n do y[i]:=0; 18 for i:= 1 to n do inc(c[y[i]]); 19 for i:= 1 to n do inc(c[i],c[i-1]); 20 for i:= 1 to n do 21 begin 22 sa[c[y[i]]]:=i; 23 dec(c[y[i]]); 24 end; 25 fillchar(c,sizeof(c),0); 26 for i:= 1 to n do x[i]:=rank[i]; 27 for i:= 1 to n do inc(c[x[i]]); 28 for i:= 1 to n do inc(c[i],c[i-1]); 29 for i:= n downto 1 do 30 begin 31 y[sa[i]]:=c[x[sa[i]]]; 32 dec(c[x[sa[i]]]); 33 end; 34 for i:= 1 to n do sa[y[i]]:=i; 35 tot:=1; 36 rank[sa[1]]:=1; 37 for i:= 2 to n do 38 begin 39 if (x[sa[i]]<>x[sa[i-1]]) or (x[sa[i]+p]<>x[sa[i-1]+p]) then inc(tot); 40 rank[sa[i]]:=tot; 41 end; 42 p:=p<<1; 43 end; 44 end; 45 46 procedure makeht; 47 var i,j,p:longint; 48 begin 49 h[1]:=0; p:=0; 50 for i:= 1 to n do 51 begin 52 p:=max(p-1,0); 53 if rank[i]=1 then continue; 54 j:=sa[rank[i]-1]; 55 while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p); 56 h[rank[i]]:=p; 57 end; 58 end; 59 60 procedure init; 61 var i,j,tot:longint; 62 ch:char; 63 begin 64 readln(n,time); 65 for i:= 1 to n do readln(s[i]); 66 for i:= 1 to n do x[i]:=s[i]; 67 fillchar(c,sizeof(c),0); 68 for i:= 1 to n do inc(c[x[i]]); 69 for i:= 1 to 180 do inc(c[i],c[i-1]); 70 for i:= 1 to n do 71 begin 72 sa[c[x[i]]]:=i; 73 dec(c[x[i]]); 74 end; 75 rank[sa[1]]:=1; 76 tot:=1; 77 for i:= 2 to n do 78 begin 79 if x[sa[i]]<>x[sa[i-1]] then inc(tot); 80 rank[sa[i]]:=tot; 81 end; 82 make; 83 makeht; 84 end; 85 86 function check(k:longint):boolean; 87 var i,j,x,y:longint; 88 begin 89 i:=1; 90 while i<=n do 91 begin 92 j:=i; 93 while (j<n) and (h[j+1]>=k) do inc(j); 94 if j-i+1>=time then exit(true); 95 i:=j+1; 96 end; 97 exit(false); 98 end; 99 100 procedure solve; 101 var l,r,mid,ans:longint; 102 begin 103 l:=0; r:=n>>1; ans:=0; 104 while l<=r do 105 begin 106 mid:=(l+r)>>1; 107 if check(mid) then 108 begin 109 l:=mid+1; 110 ans:=mid; 111 end 112 else r:=mid-1; 113 end; 114 writeln(ans); 115 end; 116 117 Begin 118 init; 119 solve; 120 End.
时间: 2024-10-12 23:57:59