首页 > 代码库 > BZOJ3676: [Apio2014]回文串

BZOJ3676: [Apio2014]回文串

Description

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

Input

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

Output


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

Sample Input

【样例输入l】
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 }

 

BZOJ3676: [Apio2014]回文串