首先后缀数组预处理
然后二分答案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.
View Code

 

posted on 2014-09-05 22:41  acphile  阅读(186)  评论(0编辑  收藏  举报