zoukankan      html  css  js  c++  java
  • bzoj2565

    网络流就先告一段落了

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

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

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

    要解决最长回文序列,首先要倒序添加原串然后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
  • 相关阅读:
    Poj 2017 Speed Limit(水题)
    Poj 1316 Self Numbers(水题)
    Poj 1017 Packets(贪心策略)
    Poj 1017 Packets(贪心策略)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2000 Gold Coins(水题)
    poj 2000 Gold Coins(水题)
  • 原文地址:https://www.cnblogs.com/phile/p/4473224.html
Copyright © 2011-2022 走看看