zoukankan      html  css  js  c++  java
  • BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)

    Description

    考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出 
    现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 
    大出现值。 

    Input

    输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。 

    Output

    输出一个整数,为逝查回文子串的最大出现值。 

    Sample Input

    【样例输入l】
    abacaba
    【样例输入2]
    www

    Sample Output

    【样例输出l】
    7
    【样例输出2]
    4

    解题思路:

    1.Manacher+SAM

    首先,是不是有人告诉过你本质不同的回文串有O(n)个,就是在Manacher中学过的。

    每次在Manacher扩展f[i]时将其在SAM的Parent树中匹配,就是len*wgt最大值。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 const int N=600005;
      6 const int M=300005;
      7 struct sant{
      8     int tranc[26];
      9     int len;
     10     int pre;
     11 }s[N];
     12 struct pnt{
     13     int hd;
     14     int fa[17];
     15     int wgt;
     16 }p[N];
     17 int cnt;
     18 int dfn;
     19 int siz;
     20 int fin;
     21 int len,m;
     22 lnt ans;
     23 char tmp[M];
     24 int str[M<<1];
     25 int f[N];
     26 int pos[M<<1];
     27 int endpos[M];
     28 int has[N];
     29 int topo[N];
     30 void Insert(int c)
     31 {
     32     int nwp,nwq,lsp,lsq;
     33     nwp=++siz;
     34     p[nwp].wgt=1;
     35     s[nwp].len=s[fin].len+1;
     36     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
     37         s[lsp].tranc[c]=nwp;
     38     if(!lsp)
     39         s[nwp].pre=1;
     40     else{
     41         lsq=s[lsp].tranc[c];
     42         if(s[lsq].len==s[lsp].len+1)
     43             s[nwp].pre=lsq;
     44         else{
     45             nwq=++siz;
     46             s[nwq]=s[lsq];
     47             s[nwq].len=s[lsp].len+1;
     48             s[nwp].pre=s[lsq].pre=nwq;
     49             while(s[lsp].tranc[c]==lsq)
     50             {
     51                 s[lsp].tranc[c]=nwq;
     52                 lsp=s[lsp].pre;
     53             }
     54         }
     55     }
     56     fin=nwp;
     57     return ;
     58 }
     59 int check(int l,int r)
     60 {
     61     if(l<1||r>len)
     62         return 0;
     63     int root=endpos[r];
     64     for(int i=16;i>=0;i--)
     65     {
     66         if(s[p[root].fa[i]].len>=r-l+1)
     67             root=p[root].fa[i];
     68     }
     69     ans=std::max(ans,(lnt)(r-l+1)*(lnt)(p[root].wgt));
     70     return (r-l+1)*p[root].wgt;
     71 }
     72 int main()
     73 {
     74     scanf("%s",tmp+1);
     75     fin=++siz;
     76     len=strlen(tmp+1);
     77     for(int i=1;i<=len;i++)
     78     {
     79         Insert(tmp[i]-'a');
     80         endpos[i]=fin;
     81     }
     82     for(int i=1;i<=siz;i++)
     83         has[s[i].len]++;
     84     for(int i=1;i<=siz;i++)
     85         has[i]+=has[i-1];
     86     for(int i=1;i<=siz;i++)
     87         topo[has[s[i].len]--]=i;
     88     for(int i=siz;i;i--)
     89     {
     90         int x=topo[i];
     91         p[s[x].pre].wgt+=p[x].wgt;
     92     }
     93     for(int i=1;i<=siz;i++)
     94     {
     95         int x=topo[i];
     96         p[x].fa[0]=s[x].pre;
     97         p[1].fa[0]=1;
     98         for(int j=1;j<=16;j++)
     99             p[x].fa[j]=p[p[x].fa[j-1]].fa[j-1];
    100     }
    101     int tmpl=0;
    102     str[++tmpl]='*';
    103     for(int i=1;i<=len;i++)
    104     {
    105         str[++tmpl]='#';
    106         str[++tmpl]=tmp[i];
    107         pos[tmpl]=i;
    108     }
    109     str[++tmpl]='#';
    110     str[++tmpl]='$';
    111     int now=0;
    112     for(int i=1;i<=tmpl;i++)
    113     {
    114         f[i]=std::min(f[now]+now-i,f[now*2-i]);
    115         f[i]=std::max(f[i],1);
    116         check(pos[i-f[i]+2],pos[i+f[i]-2]);
    117         while(str[i-f[i]]==str[i+f[i]])
    118         {
    119             f[i]++;
    120             check(pos[i-f[i]+2],pos[i+f[i]-2]);
    121         }
    122         if(f[now]+now<f[i]+i)
    123             now=i;
    124     }
    125     printf("%lld
    ",ans);
    126     return 0;
    127 }

     2.PAM模板

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long lnt;
     5 struct pant{
     6     int tranc[26];
     7     int pre;
     8     int len;
     9     int wgt;
    10 };
    11 namespace PAM{
    12     pant h[1000000];
    13     int siz;
    14     int fin;
    15     void Res(void)
    16     {
    17         fin=0;
    18         siz=1;
    19         h[0].pre=h[1].pre=1;
    20         h[1].len=-1;
    21         return ;
    22     }
    23     bool mismatch(char *a,int i,int pa)
    24     {
    25         return a[i-h[pa].len-1]!=a[i];
    26     }
    27     void Insert(char *a,int i)
    28     {
    29         int nwp,lsp,mac;
    30         lsp=fin;
    31         int c=a[i]-'a';
    32         while(mismatch(a,i,lsp))
    33             lsp=h[lsp].pre;
    34         if(!h[lsp].tranc[c])
    35         {
    36             nwp=++siz;
    37             mac=h[lsp].pre;
    38             h[nwp].len=h[lsp].len+2;
    39             while(mismatch(a,i,mac))
    40                 mac=h[mac].pre;
    41             h[nwp].pre=h[mac].tranc[c];
    42             h[lsp].tranc[c]=nwp;
    43         }
    44         fin=h[lsp].tranc[c];
    45         h[fin].wgt++;
    46         return ;
    47     }
    48     lnt build(void)
    49     {
    50         lnt ans=0;
    51         for(int i=siz;i;i--)
    52         {
    53             h[h[i].pre].wgt+=h[i].wgt;
    54             ans=std::max(ans,(lnt)(h[i].len)*(lnt)(h[i].wgt));
    55         }
    56         return ans;
    57     }
    58 }
    59 char tmp[1000000];
    60 int main()
    61 {
    62     PAM::Res();
    63     scanf("%s",tmp+1);
    64     int len=strlen(tmp+1);
    65     for(int i=1;i<=len;i++)
    66         PAM::Insert(tmp,i);
    67     printf("%lld
    ",PAM::build());
    68     return 0;
    69 }
  • 相关阅读:
    axure 用中继器实现下拉多选框
    excel 常用全局变量
    win10 x64 python3.6 pycharm 安装statsmodels
    Oracle 10进制转36进制
    概念数据模型设计与逻辑数据模型设计、物理数据模型设计的关系
    does not support ASP.NET compatibility 错误
    Oracle日志文件管理与查看
    oradmin相关用法
    Oracle Standby Database 实现方案
    c# 调用zebra打印指令 打印到USB端口
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10046219.html
Copyright © 2011-2022 走看看