网络流就先告一段落了

在进行其他训练之前,我决定先练一道后缀数组(对这个我还是比较有自信的)

虽然之前没用后缀数组解决过回文问题,但是稍微想想就知道,

要解决最长双倍回文,首先要解决最长回文序列,

要解决最长回文序列,首先要倒序添加原串然后LCP

任意两个后缀的LCP我就不多说了,

然后我们就可以求出以任意一个字符为中心展开的最长回文串(要小心,偶数长度的最长回文串)

然后就能求出每个字符向左向右延伸回文串能延伸多远,

最后在遍历一边就可以了。

  1 var h,sa,rank,x,y,sum:array[0..210000] of longint;
  2     f:array[0..200010,0..20] of longint;
  3     d:array[0..20] of longint;
  4     left,right:array[0..100010] of longint;
  5     p,i,j,l,n,m,ans,t:longint;
  6     s:ansistring;
  7 
  8 function min(a,b:longint):longint;
  9   begin
 10     if a>b then exit(b) else exit(a);
 11   end;
 12 
 13 function max(a,b:longint):longint;
 14   begin
 15     if a>b then exit(a) else exit(b);
 16   end;
 17 
 18 procedure swap(var a,b:longint);
 19   var c:longint;
 20   begin
 21     c:=a;
 22     a:=b;
 23     b:=c;
 24   end;
 25 
 26 procedure suffix;
 27   var m,p,i,j:longint;
 28   begin
 29     for i:=1 to n do
 30     begin
 31       y[i]:=ord(s[i]);
 32       inc(sum[y[i]]);
 33     end;
 34     m:=255;
 35     for i:=2 to m do
 36       inc(sum[i],sum[i-1]);
 37     for i:=n downto 1 do
 38     begin
 39       sa[sum[y[i]]]:=i;
 40       dec(sum[y[i]]);
 41     end;
 42     p:=1;
 43     rank[sa[1]]:=1;
 44     for i:=2 to n do
 45     begin
 46       if y[sa[i]]<>y[sa[i-1]] then inc(p);
 47       rank[sa[i]]:=p;
 48     end;
 49     m:=p;
 50     j:=1;
 51     while m<n do
 52     begin
 53       y:=rank;
 54       fillchar(sum,sizeof(sum),0);
 55       p:=0;
 56       for i:=n-j+1 to n do
 57       begin
 58         inc(p);
 59         x[p]:=i;
 60       end;
 61       for i:=1 to n do
 62         if sa[i]>j then
 63         begin
 64           inc(p);
 65           x[p]:=sa[i]-j;
 66         end;
 67       for i:=1 to n do
 68       begin
 69         rank[i]:=y[x[i]];
 70         inc(sum[rank[i]]);
 71       end;
 72       for i:=2 to m do
 73         inc(sum[i],sum[i-1]);
 74       for i:=n downto 1 do
 75       begin
 76         sa[sum[rank[i]]]:=x[i];
 77         dec(sum[rank[i]]);
 78       end;
 79       p:=1;
 80       rank[sa[1]]:=1;
 81       for i:=2 to n do
 82       begin
 83         if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p);
 84         rank[sa[i]]:=p;
 85       end;
 86       m:=p;
 87       j:=j shl 1;
 88     end;
 89     h[1]:=0;
 90     p:=0;
 91     for i:=1 to n do
 92     begin
 93       if rank[i]=1 then continue;
 94       j:=sa[rank[i]-1];
 95       while s[i+p]=s[j+p] do inc(p);
 96       h[rank[i]]:=p;
 97       if p>0 then dec(p);
 98     end;
 99   end;
100 
101 procedure rmq;
102   begin
103     t:=trunc(ln(n)/ln(2));
104     d[0]:=1;
105     for i:=1 to t do
106       d[i]:=d[i-1]*2;
107 
108     for i:=1 to n do
109       f[i,0]:=h[i];
110     for j:=1 to t do
111       for i:=1 to n do
112         if (i+d[j]-1<=n) then
113           f[i,j]:=min(f[i,j-1],f[i+d[j-1],j-1]);
114   end;
115 
116 function ask(x,y:longint):longint;
117   var k:longint;
118   begin
119     if x>y then swap(x,y);
120     inc(x);
121     k:=trunc(ln(y-x+1)/ln(2));
122     ask:=min(f[x,k],f[y-d[k]+1,k]);
123   end;
124 
125 begin
126   readln(s);
127   l:=length(s);
128   s:=s+'*';
129   for i:=l downto 1 do
130   begin
131     s:=s+s[i];
132     left[i]:=1;
133     right[i]:=1;
134   end;
135   n:=length(s);
136   suffix;
137   rmq;
138   for i:=1 to l do
139   begin
140     p:=ask(rank[i],rank[n+1-i]);  //先求奇数长度的回文序列
141     left[i-p+1]:=max(left[i-p+1],p*2-1);
142     right[i+p-1]:=max(right[i+p-1],p*2-1);
143     if i<>l then
144     begin
145       p:=ask(rank[i],rank[n-i]);  //偶数长度的回文序列
146       if p>1 then dec(p);    //细节
147       if p<>0 then
148       begin
149         left[i-p+1]:=max(left[i-p+1],2*p);
150         right[i+p]:=max(right[i+p],2*p);
151       end;
152     end;
153   end;
154   for i:=l-1 downto 1 do  //处理每个字符为回文串的一端的最远延伸
155     right[i]:=max(right[i],right[i+1]-2);
156   for i:=2 to l do
157     left[i]:=max(left[i],left[i-1]-2);
158   for i:=1 to l-1 do  //不难理解
159     ans:=max(ans,right[i]+left[i+1]);
160   writeln(ans);
161 end.
View Code

 

posted on 2014-06-29 22:29  acphile  阅读(215)  评论(0编辑  收藏  举报