HYSBZ 3676 回文串 (回文树)
3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1680 Solved: 707
[Submit][Status][Discuss]
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
【样例输入l】
abacaba
【样例输入2]
www
abacaba
【样例输入2]
www
Sample Output
【样例输出l】
7
【样例输出2]
4
7
【样例输出2]
4
回文树模板题
#include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <stdio.h> #include <stdlib.h> using namespace std; typedef long long int LL; const int maxn=3e5+10; char str[maxn]; struct Tree { int next[maxn][26]; int fail[maxn]; int num[maxn]; LL cnt[maxn]; int len[maxn]; int s[maxn]; int p; int n; int last; int new_node(int x) { memset(next[p],0,sizeof(next[p])); cnt[p]=0; num[p]=0; len[p]=x; return p++; } void init() { p=0; new_node(0); new_node(-1); last=0;n=0; s[0]=-1; fail[0]=1; } int get_fail(int x) { while(s[n-len[x]-1]!=s[n]) x=fail[x]; return x; } int add(int x) { x-='a'; s[++n]=x; int cur=get_fail(last); if(!(last=next[cur][x])) { int now=new_node(len[cur]+2); fail[now]=next[get_fail(fail[cur])][x]; next[cur][x]=now; num[now]=num[fail[now]]+1; last=now; } cnt[last]++; } void count() { for(int i=p-1;i>=0;i--) cnt[fail[i]]+=cnt[i]; } }tree; int main() { while(scanf("%s",str)!=EOF) { int len=strlen(str); tree.init(); for(int i=0;i<len;i++) tree.add(str[i]); tree.count(); LL ans=0; for(int i=2;i<tree.p;i++) ans=max(ans,(LL)tree.cnt[i]*tree.len[i]); printf("%lld\n",ans); } return 0; }