网络流就先告一段落了
在进行其他训练之前,我决定先练一道后缀数组(对这个我还是比较有自信的)
虽然之前没用后缀数组解决过回文问题,但是稍微想想就知道,
要解决最长双倍回文,首先要解决最长回文序列,
要解决最长回文序列,首先要倒序添加原串然后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.