D - 回文串 HYSBZ - 3676

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

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

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

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

Sample Output
【样例输出l】
7
【样例输出2]
4
Hint

一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中:
● a出现4次,其出现值为4:1:1=4
● b出现2次,其出现值为2:1:1=2
● c出现1次,其出现值为l:1:l=l
● aba出现2次,其出现值为2:1:3=6
● aca出现1次,其出现值为1=1:3=3
●bacab出现1次,其出现值为1:1:5=5
● abacaba出现1次,其出现值为1:1:7=7
故最大回文子串出现值为7。
【数据规模与评分】
数据满足1≤字符串长度≤300000。

题解:裸回文自动机,只要求出cnt数组即可,一遍求的时候一遍比较,长度就是len数组

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef  long long ll;
const int maxn=3e5+10;
const int N=26;
struct PAM
{
  int len[maxn],fail[maxn];
  int cnt[maxn],S[maxn];
  int ch[maxn][N],num[maxn];
  int last,p,n;
  int nowcode(int x)
  {
    for(int i=0;i<N;i++) ch[p][i]=0;
    cnt[p]=0;num[p]=0;len[p]=x;
    return p++;
  }
  void init()
  {
    last=p=n=0;
    nowcode(0);
    nowcode(-1);
    S[0]=-1;
    fail[0]=1;
  }
  int get_fail(int x)
  {
    while(S[n-len[x]-1]!=S[n]) x=fail[x];
    return x;
  }
  void add(int c)
  {
    c=c-'a';
    S[++n]=c;
    int cur=get_fail(last);
    if(!ch[cur][c])
    {
      int now=nowcode(len[cur]+2);
      fail[now]=ch[get_fail(fail[cur])][c];
      ch[cur][c]=now;
      num[now]=num[fail[cur]]+1;
    }
    last=ch[cur][c];
    cnt[last]++;
  }
  void count()
  {
    ll res=0;
    for(int i=p-1;i>=0;i--)
    {
      cnt[fail[i]]+=cnt[i];
      res=max(res,1ll*len[i]*cnt[i]);
    }
    printf("%lld\n",res);
  }
};
PAM T;
char s[maxn];
void slove()
{
  T.init();
  int n=strlen(s);
  for(int i=0;i<n;i++) T.add(s[i]);
  T.count();
}
int main()
{
    while(~scanf("%s",s))
    {
      slove();
    }
}

发布了547 篇原创文章 · 获赞 14 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览