首先后缀数组预处理
然后二分答案len很显然,然后考虑怎么判定
我们用左右指针顺着名次扫描一下,初始左右指针为1
根据LCP(i,j)=min(height[rank[i]+1]~height[rank[j]]) 设rank[i]<rank[j]
移动右指针扫描得到一组后缀[i,j]之间LCP>=len,h[j+1]<len
然后判断一下这组后缀是否有超过半数的原串,如果满足则记录
然后左右指针都从j+1开始
由于每个后缀最多被扫描一次判断一次,所以必然O(n)
注意多个串相连接的时候要用不同的字符作为分隔符
1 var ans,x,y,sa,sum,rank,h,loc:array[0..200010] of longint; 2 v:array[0..500] of boolean; 3 j,len,l,r,k,i,n,m,p,tot:longint; 4 s,ch:ansistring; 5 6 procedure suffix; 7 begin 8 fillchar(sum,sizeof(sum),0); 9 for i:=1 to n do 10 begin 11 y[i]:=ord(s[i]); 12 inc(sum[y[i]]); 13 end; 14 m:=255; 15 for i:=1 to m do 16 sum[i]:=sum[i-1]+sum[i]; 17 for i:=n downto 1 do 18 begin 19 sa[sum[y[i]]]:=i; 20 dec(sum[y[i]]); 21 end; 22 p:=1; 23 rank[sa[1]]:=1; 24 for i:=2 to n do 25 begin 26 if (y[sa[i]]<>y[sa[i-1]]) then inc(p); 27 rank[sa[i]]:=p; 28 end; 29 m:=p; 30 j:=1; 31 while m<n do 32 begin 33 fillchar(sum,sizeof(sum),0); 34 y:=rank; 35 p:=0; 36 for i:=n-j+1 to n do 37 begin 38 inc(p); 39 x[p]:=i; 40 end; 41 for i:=1 to n do 42 if sa[i]>j then 43 begin 44 inc(p); 45 x[p]:=sa[i]-j; 46 end; 47 48 for i:=1 to n do 49 begin 50 rank[i]:=y[x[i]]; 51 inc(sum[rank[i]]); 52 end; 53 for i:=1 to m do 54 inc(sum[i],sum[i-1]); 55 for i:=n downto 1 do 56 begin 57 sa[sum[rank[i]]]:=x[i]; 58 dec(sum[rank[i]]); 59 end; 60 p:=1; 61 rank[sa[1]]:=1; 62 for i:=2 to n do 63 begin 64 if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p); 65 rank[sa[i]]:=p; 66 end; 67 m:=p; 68 j:=j shl 1; 69 end; 70 h[1]:=0; 71 p:=0; 72 for i:=1 to n do 73 begin 74 if rank[i]=1 then continue; 75 j:=sa[rank[i]-1]; 76 while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p); 77 h[rank[i]]:=p; 78 if p>0 then dec(p); 79 end; 80 end; 81 82 function solve(l,r:longint):boolean; 83 var i,t:longint; 84 begin 85 fillchar(v,sizeof(v),false); 86 t:=0; 87 for i:=l to r do 88 if (loc[sa[i]]<>-1) then 89 if not v[loc[sa[i]]] then 90 begin 91 inc(t); 92 v[loc[sa[i]]]:=true; 93 end; 94 if t>k shr 1 then exit(true) else exit(false); 95 end; 96 97 function check(len:longint):boolean; 98 var b,e,i:longint; 99 fl:boolean; 100 101 begin 102 fl:=false; 103 b:=1; 104 e:=1; 105 for i:=2 to n do 106 begin 107 if h[i]>=len then inc(e) 108 else begin 109 if solve(b,e) then 110 begin 111 if not fl then tot:=0; 112 fl:=true; 113 inc(tot); 114 ans[tot]:=sa[b]; 115 end; 116 b:=i; 117 e:=i; 118 end; 119 end; 120 if b<e then //注意收尾 121 begin 122 if solve(b,e) then 123 begin 124 if not fl then tot:=0; 125 inc(tot); 126 fl:=true; 127 ans[tot]:=sa[b]; 128 end; 129 end; 130 exit(fl); 131 end; 132 133 begin 134 readln(k); 135 while k<>0 do 136 begin 137 s:=''; 138 r:=0; 139 m:=0; 140 for i:=1 to k do 141 begin 142 readln(ch); 143 if r<length(ch) then r:=length(ch); 144 for j:=1 to length(ch) do 145 begin 146 inc(m); 147 loc[m]:=i; 148 end; 149 inc(m); 150 loc[m]:=-1; 151 s:=s+ch+chr(i); 152 end; 153 n:=length(s); 154 suffix; 155 l:=1; 156 len:=0; 157 while l<=r do 158 begin 159 m:=(l+r) shr 1; 160 if check(m) then 161 begin 162 len:=m; 163 l:=m+1; 164 end 165 else r:=m-1; 166 end; 167 if k=1 then 168 begin 169 writeln(s); 170 writeln; 171 end 172 else if len=0 then 173 begin 174 writeln('?'); 175 writeln; 176 end 177 else begin 178 for i:=1 to tot do 179 begin; 180 for j:=ans[i] to ans[i]+len-1 do 181 write(s[j]); 182 writeln; 183 end; 184 writeln; 185 end; 186 readln(k); 187 end; 188 end.