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
  • 相关阅读:
    游戏编程模式--原型模式
    游戏编程模式--观察者模式
    游戏编程模式--享元模式
    游戏编程模式--命令模式
    mybatis的线程安全
    开发遇到的问题
    spring的ThreadLocal解决线程安全
    i++
    jvm内存初步了解
    注解@RequestMapping,@RequestBody
  • 原文地址:https://www.cnblogs.com/phile/p/4473224.html
Copyright © 2011-2022 走看看