• 【APIO2014T1】回文串-回文自动机(PAM)模板题


    测试地址:回文串

    做法:这道题可以用Manacher+后缀数组来做,但是很慢,于是本人用了一个上午去学习了回文自动机(Palindromic Automaton,PAM)这个东西,它是一个可以接受字符串的所有回文子串的自动机,并且可以很方便地求出所有本质不同的回文子串的一些信息,教程可以看这个。看完之后其实这就是一道PAM的裸题了,求出每一个本质不同的回文子串的长度和出现的次数,然后枚举求最大值就可以了。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    int n,now=0,tot=1,pos;
    ll ans=0;
    char s[300010];
    struct PAMnode
    {
      ll len,cnt;
      int fail,ch[30];
    }nd[300010];
    
    int getfail(int x)
    {
      while (s[pos-nd[x].len-1]!=s[pos]) x=nd[x].fail;
      return x;
    }
    
    void insert(int c)
    {
      c-='a';
      now=getfail(now);
      if (!nd[now].ch[c])
      {
        int son=++tot;
        nd[now].ch[c]=son;
    	nd[son].fail=nd[getfail(nd[now].fail)].ch[c];
    	nd[son].len=nd[now].len+2;
    	nd[son].cnt=1;
    	for(int i=0;i<=25;i++) nd[son].ch[i]=0;
      }
      else nd[nd[now].ch[c]].cnt++;
      now=nd[now].ch[c];
    }
    
    int main()
    {
      s[0]='#';
      scanf("%s",&s[1]);
      n=strlen(s)-1;
      
      nd[0].len=nd[0].cnt=0,nd[0].fail=1;
      for(int i=0;i<=25;i++) nd[0].ch[i]=0;
      nd[1].len=nd[n+1].len=-1,nd[1].fail=n+1,nd[1].cnt=0;
      for(int i=0;i<=25;i++) nd[1].ch[i]=nd[n+1].ch[i]=0;
      
      for(pos=1;pos<=n;pos++)
        insert(s[pos]);
      for(int i=tot;i>=2;i--)
        nd[nd[i].fail].cnt+=nd[i].cnt;
      for(int i=2;i<=tot;i++)
        ans=max(ans,nd[i].len*nd[i].cnt);
      
      printf("%lld",ans);
      
      return 0;
    }
    


  • 相关阅读:
    链接
    Oracle创建表空间
    C#中的全局异常捕捉
    软件架构入门
    Nginx安装及配置详解包括windows环境
    极路由4增强版(B70)HC5962离线ROOT通过Breed刷openwrt教程
    vue自定义全局指令v-emoji限制input输入表情和特殊字符
    【vue】@input
    【window】常用软件
    Vbox 虚拟机全屏
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793759.html
Copyright © 2020-2023  润新知