好像已经很久没有做后缀数组的题目,导致这种题一开始没想出来
看到公共子串肯定想到后缀数组吧,但我都忘了最长公共子串怎么求了
重要的性质:最长公共子串=max(h[i])名次相邻的两个后缀要分别属于s1,s2串 具体怎么证很简单
这道题多了一个条件,就是公用子串不能包含某个串——很明显想到KMP
我们可以预处理与s3匹配的起始位置,然后处理每个点右边最近的起始位置
然后在穷举h[i]的时候判断一下即可
1 var h,f,x,y,sum,sa,rank:array[0..120000] of longint; 2 v:array[0..120000] of boolean; 3 j,t,st,en,ans,i,p,l,n,m:longint; 4 s,ss:ansistring; 5 fl:boolean; 6 7 function max(a,b:longint):longint; 8 begin 9 if a>b then exit(a) else exit(b); 10 end; 11 12 procedure suffix; 13 var i,p,j,m:longint; 14 begin 15 m:=150; 16 for i:=1 to n do 17 begin 18 y[i]:=ord(s[i]); 19 inc(sum[y[i]]); 20 end; 21 for i:=1 to m do 22 inc(sum[i],sum[i-1]); 23 for i:=n downto 1 do 24 begin 25 sa[sum[y[i]]]:=i; 26 dec(sum[y[i]]); 27 end; 28 p:=1; 29 rank[sa[1]]:=1; 30 for i:=2 to n do 31 begin 32 if y[sa[i]]<>y[sa[i-1]] then inc(p); 33 rank[sa[i]]:=p; 34 end; 35 m:=p; 36 j:=1; 37 while m<n do 38 begin 39 y:=rank; 40 fillchar(sum,sizeof(sum),0); 41 p:=0; 42 for i:=n-j+1 to n do 43 begin 44 inc(p); 45 x[p]:=i; 46 end; 47 for i:=1 to n do 48 if sa[i]>j then 49 begin 50 inc(p); 51 x[p]:=sa[i]-j; 52 end; 53 for i:=1 to n do 54 begin 55 rank[i]:=y[x[i]]; 56 inc(sum[rank[i]]); 57 end; 58 for i:=1 to m do 59 inc(sum[i],sum[i-1]); 60 for i:=n downto 1 do 61 begin 62 sa[sum[rank[i]]]:=x[i]; 63 dec(sum[rank[i]]); 64 end; 65 p:=1; 66 rank[sa[1]]:=1; 67 for i:=2 to n do 68 begin 69 if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i-1]+j]<>y[sa[i]+j]) then inc(p); 70 rank[sa[i]]:=p; 71 end; 72 m:=p; 73 j:=j shl 1; 74 end; 75 p:=0; 76 h[1]:=0; 77 for i:=1 to n do 78 begin 79 if rank[i]=1 then continue; 80 j:=sa[rank[i]-1]; 81 while s[i+p]=s[j+p] do inc(p); 82 h[rank[i]]:=p; 83 if p>0 then dec(p); 84 end; 85 end; 86 87 begin 88 readln(s); 89 readln(ss); 90 p:=length(s)+1; 91 s:=s+chr(1)+ss+chr(2); 92 n:=length(s); 93 94 readln(ss); 95 l:=length(ss); 96 ss:=ss+' '; 97 for i:=2 to l do 98 begin 99 j:=f[i-1]; 100 while (j>0) and (ss[j+1]<>ss[i]) do j:=f[j]; 101 if ss[j+1]=ss[i] then f[i]:=j+1 else f[i]:=0; 102 end; 103 104 j:=0; 105 for i:=1 to p-1 do 106 begin 107 while (j>0) and (ss[j+1]<>s[i]) do j:=f[j]; 108 if ss[j+1]=s[i] then 109 begin 110 inc(j); 111 if j=l then v[i-l+1]:=true; 112 end 113 else j:=0; 114 end; 115 116 t:=100000007; 117 for i:=p-1 downto 1 do 118 begin 119 if v[i] then t:=i; 120 f[i]:=t; //右边最近的匹配起始节点 121 end; 122 suffix; 123 ans:=0; 124 for i:=2 to n do 125 begin 126 fl:=false; 127 if (sa[i]<p) and (sa[i-1]>p) and (sa[i-1]<n) then 128 begin 129 st:=sa[i]; 130 en:=f[st]; 131 fl:=true; 132 end; 133 if (sa[i]>p) and (sa[i]<n) and (sa[i-1]<p) then 134 begin 135 st:=sa[i-1]; 136 en:=f[st]; 137 fl:=true; 138 end; 139 if fl then 140 begin 141 if h[i]>=en-st+l then //判断是否包含了匹配串 142 ans:=max(ans,en-st+l-1) 143 else ans:=max(ans,h[i]); 144 end; 145 end; 146 writeln(ans); 147 end.