BZOJ 3676: [Apio2014]回文串

3676: [Apio2014]回文串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 904  Solved: 356

Description

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

Input

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

Output


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

Sample Input

【样例输入1】

abacaba

【样例输入2】

www

Sample Output

【样例输出1】

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。

解题:回文树

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 300010;
 5 const int N = 26;
 6 struct PalindromicTree {
 7     int next[maxn][N],fail[maxn],cnt[maxn];
 8     int s[maxn],len[maxn],last,tot,n;
 9     int newnode(int length) {
10         cnt[tot] = 0;
11         memset(next[tot],0,sizeof next[tot]);
12         len[tot] = length;
13         return tot++;
14     }
15     int get_fail(int x) {
16         while(s[n - len[x] - 1] != s[n]) x = fail[x];
17         return x;
18     }
19     void init() {
20         last = tot = n = 0;
21         newnode(0);
22         newnode(-1);
23         s[n] = -1;
24         fail[0] = 1;
25     }
26     void add(int c) {
27         c -= 'a';
28         s[++n] = c;
29         int cur = get_fail(last);
30         if(!next[cur][c]) {
31             int now = newnode(len[cur] + 2);
32             fail[now] = next[get_fail(fail[cur])][c];
33             next[cur][c] = now;
34         }
35         last = next[cur][c];
36         cnt[last]++;
37     }
38     void count() {
39         for(int i = tot - 1; i > 1; --i)
40             cnt[fail[i]] += cnt[i];
41     }
42 } PT;
43 char str[maxn];
44 int main() {
45     while(~scanf("%s",str)) {
46         PT.init();
47         for(int i = 0; str[i]; ++i) PT.add(str[i]);
48         PT.count();
49         LL ret = 0;
50         for(int i = 2; i < PT.tot; ++i)
51             ret = max(ret,(LL)PT.len[i]*PT.cnt[i]);
52         printf("%lld\n",ret);
53     }
54     return 0;
55 }
View Code

 

posted @ 2015-08-23 17:28  狂徒归来  阅读(219)  评论(0编辑  收藏  举报