BZOJ3676: [Apio2014]回文串
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
回文树模板题,虽然知道可以在SAM上倍增爆搞
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=300010; 5 struct PAM{ 6 int cnt,last; 7 int a[N][26],sz[N],l[N],f[N]; 8 char s[N]; 9 PAM(){ 10 cnt=f[0]=f[1]=1; 11 l[1]=-1; 12 } 13 int get_fail(int x,int loc){ 14 while(s[loc-l[x]-1]!=s[loc])x=f[x]; 15 return x; 16 } 17 void insert(int c,int loc){ 18 int p=get_fail(last,loc); 19 if(!a[p][c]){ 20 int now=++cnt,k=get_fail(f[p],loc); 21 l[now]=l[p]+2; 22 f[now]=a[k][c];a[p][c]=now; 23 } 24 last=a[p][c]; 25 ++sz[last]; 26 } 27 ll calc(){ 28 ll res=0; 29 for(int i=cnt;i;--i){ 30 sz[f[i]]+=sz[i]; 31 res=max(res,(ll)sz[i]*l[i]); 32 } 33 return res; 34 } 35 }P; 36 int main(){ 37 scanf("%s",P.s); 38 int n=strlen(P.s); 39 for(int i=0;i<n;++i) 40 P.insert(P.s[i]-'a',i); 41 printf("%lld\n",P.calc()); 42 return 0; 43 }