zoukankan      html  css  js  c++  java
  • 【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;
    }
    


  • 相关阅读:
    "LC.exe" exited with code -1 错误
    GridControl的用法(1)
    oracle建库及plsql建表空间的用法
    sql server还原数据库文件(.bak)常见问题解决办法笔记
    ubuntu下安装deb包
    ubuntu下安装五笔输入法
    ubuntu下安装codeTyphon
    centos7下源码安装lazarus
    后台对Json数据加密、解密
    Http请求纯后台简单实现分页并返回JSON格式
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793758.html
Copyright © 2011-2022 走看看