zoukankan      html  css  js  c++  java
  • 字符串:回文自动机

    类似AC自动机的一种回文串匹配自动机,也就是一棵字符树。

    准确的说,是两颗字符树

    0号表示回文串长度为偶数的树,1号表示回文串长度为奇数的树

    每一个节点都代表一个字符串,并且类似AC自动机那样,有字符基个儿子

    它的第i个儿子就表示将字符基的第i个字符接到它表示的字符串两边形成的字符串

    BZOJ3676

    给定一个字符串,找出这个字符串所有的回文子串,然后找一个回文子串出现次数×回文子串长度的最大值

    用manacher找出本质不同的回文串,每个串在后缀自动机上查询出现次数

      1 #include<set>
      2 #include<map>
      3 #include<ctime>
      4 #include<queue>
      5 #include<cmath>
      6 #include<cstdio>
      7 #include<vector>
      8 #include<cstring>
      9 #include<cstdlib>
     10 #include<iostream>
     11 #include<algorithm>
     12 #define ll long long
     13 using namespace std;
     14 int read()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     18     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     19     return x*f;
     20 }
     21 ll ans;
     22 int bin[20];
     23 int n,p[300005];
     24 char ch[300005];
     25 struct sam{
     26     int last,cnt;
     27     int fa[600005],a[600005][26],mx[600005],size[600005];
     28     int v[300005],q[600005],pos[600005],dep[600005],an[600005][19];
     29     sam(){
     30         last=++cnt;
     31     }
     32     void extend(int c,int id){
     33         int p=last,np=last=++cnt;mx[np]=mx[p]+1;
     34         size[np]=1;pos[id]=last;
     35         while(p&&!a[p][c])a[p][c]=np,p=fa[p];
     36         if(!p)fa[np]=1;
     37         else 
     38         {
     39             int q=a[p][c];
     40             if(mx[p]+1==mx[q])fa[np]=q;
     41             else 
     42             {
     43                 int nq=++cnt;mx[nq]=mx[p]+1;
     44                 memcpy(a[nq],a[q],sizeof(a[q]));
     45                 fa[nq]=fa[q];
     46                 fa[np]=fa[q]=nq;
     47                 while(a[p][c]==q)a[p][c]=nq,p=fa[p];
     48             }
     49         }
     50     }
     51     void pre(){
     52         for(int i=1;i<=cnt;i++)v[mx[i]]++;
     53         for(int i=1;i<=n;i++)v[i]+=v[i-1];
     54         for(int i=cnt;i;i--)q[v[mx[i]]--]=i;
     55         for(int i=cnt;i;i--)
     56         {
     57             int t=q[i];
     58             size[fa[t]]+=size[t];
     59         }
     60         for(int i=1;i<=cnt;i++)
     61         {
     62             int t=q[i];
     63             dep[t]=dep[fa[t]]+1;
     64             an[t][0]=fa[t];
     65             for(int j=1;bin[j]<=dep[t];j++)
     66                 an[t][j]=an[an[t][j-1]][j-1];
     67         }
     68     }
     69     void query(int l,int r){
     70         int mid=pos[r];
     71         for(int i=18;i>=0;i--)
     72         {
     73             int t=an[mid][i];
     74             if(mx[t]>=r-l+1)mid=t;
     75         }
     76         ans=max(ans,(ll)size[mid]*(r-l+1));
     77     }
     78 }sam;
     79 void manacher()
     80 {
     81     int mx=0,id;
     82     for(int i=1;i<=n;i++)
     83     {
     84         if(mx>i)p[i]=min(mx-i,p[2*id-i-1]);
     85         else p[i]=0;
     86         while(ch[i+p[i]+1]==ch[i-p[i]])
     87         {
     88             p[i]++;
     89             sam.query(i-p[i]+1,i+p[i]);
     90         }
     91         if(p[i]+i>mx)mx=p[i]+i,id=i;
     92     }
     93     mx=0;
     94     for(int i=1;i<=n;i++)
     95     {
     96         if(mx>i)p[i]=min(mx-i-1,p[2*id-i]);
     97         else {p[i]=1;sam.query(i-p[i]+1,i+p[i]-1);}
     98         while(ch[i+p[i]]==ch[i-p[i]])
     99         {
    100             p[i]++;
    101             sam.query(i-p[i]+1,i+p[i]-1);
    102         }
    103         if(p[i]+i>mx)mx=p[i]+i,id=i;
    104     }
    105 }
    106 int main()
    107 {
    108     bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
    109     scanf("%s",ch+1);
    110     n=strlen(ch+1);
    111     for(int i=1;i<=n;i++)sam.extend(ch[i]-'a',i);
    112     sam.pre();
    113     ch[0]='+';ch[n+1]='*';
    114     manacher();
    115     printf("%lld
    ",ans);
    116     return 0;
    117 }

    然后是一道回文自动机裸题

     1 #include<set>
     2 #include<map>
     3 #include<ctime>
     4 #include<queue>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<vector>
     8 #include<cstring>
     9 #include<cstdlib>
    10 #include<iostream>
    11 #include<algorithm>
    12 #define ll long long
    13 using namespace std;
    14 int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    18     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 ll ans;
    22 int n;
    23 char ch[300005];
    24 struct pam{
    25     int cnt,last;
    26     int a[300005][26],fa[300005],l[300005],size[300005];
    27     pam(){
    28         cnt=1;fa[0]=fa[1]=1;l[1]=-1;
    29     }
    30     void extend(int c,int n){
    31         int p=last;
    32         while(ch[n-l[p]-1]!=ch[n])p=fa[p];
    33         if(!a[p][c])
    34         {
    35             int now=++cnt,k=fa[p];
    36             l[now]=l[p]+2;
    37             while(ch[n-l[k]-1]!=ch[n])k=fa[k];
    38             fa[now]=a[k][c];a[p][c]=now;
    39         }
    40         last=a[p][c];
    41         size[last]++;
    42     }
    43     void solve(){
    44         for(int i=cnt;i;i--)
    45         {
    46             size[fa[i]]+=size[i];
    47             ans=max(ans,(ll)size[i]*l[i]);
    48         }
    49     }
    50 }pam;
    51 int main()
    52 {
    53     scanf("%s",ch+1);
    54     n=strlen(ch+1);
    55     for(int i=1;i<=n;i++)
    56         pam.extend(ch[i]-'a',i);
    57     pam.solve();
    58     printf("%lld
    ",ans);
    59     return 0;
    60 }
  • 相关阅读:
    对于Python中self的看法
    SpringBoot整合MyBatis-Plus快速开始
    Hive原理--体系结构
    Docker Compose + Traefik v2 快速安装, 自动申请SSL证书 http转https 初次尝试
    记录:更新VS2019后单元测试运行卡住无法运行测试的问题。
    黑帽来源页劫持代码以及如何防范
    OFFICE 2010 每次打开提示安装的问题
    Mssql 查询某记录前后N条
    验证邮箱正则表达式,包含二级域名邮箱,手机号正则表达式支持170号段
    删除TFS上的团队项目
  • 原文地址:https://www.cnblogs.com/aininot260/p/9636536.html
Copyright © 2011-2022 走看看