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

来源:互联网 发布:orange软件下载 编辑:程序博客网 时间:2024/06/05 17:09

测试地址:回文串

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

以下是本人代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define ll long longusing 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;}


0 0