洛谷传送门
BZOJ传送门
题目描述
给你一个由小写拉丁字母组成的字符串 s s 。我们定义 的一个子串的存在值为这个子串在 s s 中出现的次数乘以这个子串的长度。
对于给你的这个字符串 ,求所有回文子串中的最大存在值。
输入输出格式
输入格式:
一行,一个由小写拉丁字母( a∼z a ∼ z )组成的非空字符串 s s 。
输出格式:
输出一个整数,表示所有回文子串中的最大存在值。
输入输出样例
输入样例#1:
abacaba
输出样例#1:
7
输入样例#2:
www
输出样例#2:
4
说明
【样例解释1】
用 表示字符串 s s 的长度。
一个字符串 的子串是一个非空字符串 sisi+1…sj s i s i + 1 … s j ,其中 1≤i≤j≤|s| 1 ≤ i ≤ j ≤ | s | 。每个字符串都是自己的子串。
一个字符串被称作回文串当且仅当这个字符串从左往右读和从右往左读都是相同的。
这个样例中,有 7 7 个回文子串 , b b ,, aba a b a , aca a c a , bacab b a c a b , abacaba a b a c a b a 。他们的存在值分别为 4,2,1,6,3,5,7 4 , 2 , 1 , 6 , 3 , 5 , 7 。
所以回文子串中最大的存在值为 7 7 。
第一个子任务共 8 分,满足 。
第二个子任务共 15 分,满足 1≤|s|≤1000 1 ≤ | s | ≤ 1000 。
第三个子任务共 24 分,满足 1≤|s|≤10000 1 ≤ | s | ≤ 10000 。
第四个子任务共 26 分,满足 1≤|s|≤100000 1 ≤ | s | ≤ 100000 。
第五个子任务共 27 分,满足 1≤|s|≤300000 1 ≤ | s | ≤ 300000 。
解题分析
听说当年这道题的标算是 SAM+Manacher S A M + M a n a c h e r ,而且剧毒…
蒟蒻不会 SAM S A M 只好用 PAM P A M 水过去了…
PAM P A M 板题, 网上很多博客讲的很好, 推荐这一篇(蒟蒻这里就不献丑了…)。
代码如下:
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define R register
#define IN inline
#define gc getchar()
#define W while
#define MX 300050
struct Node
{
int to[26], cnt, fail, len, num;
}tree[MX << 1];
char buf[MX];
int arr, cur, str[MX], n;
namespace PAM
{
IN int _new(const int &val)
{tree[arr].len = val; return arr++;}
IN void init()
{
_new(0), _new(-1);
n = cur = 0; str[0] = -1;
tree[0].fail = 1;
}
IN int jump(R int now)
{
W (str[n - tree[now].len - 1] != str[n]) now = tree[now].fail;
return now;
}
IN void add(R int key)
{
key -= 'a'; str[++n] = key;
int nex = jump(cur);
if(!tree[nex].to[key])
{
int now = _new(tree[nex].len + 2);
tree[now].fail = tree[jump(tree[nex].fail)].to[key];
tree[nex].to[key] = now;
tree[now].num = tree[tree[now].fail].num + 1;
}
cur = tree[nex].to[key];
++tree[cur].cnt;
}
IN long long count()
{
long long ans = 0;
for (R int i = arr - 1; i >= 0; --i)
tree[tree[i].fail].cnt += tree[i].cnt,
ans = std::max(ans, 1ll * tree[i].cnt * tree[i].len);
return ans;
}
}
int main(void)
{
scanf("%s", buf + 1);
PAM::init(); int len = std::strlen(buf + 1);
for (R int i = 1; i <= len; ++i) PAM::add(buf[i]);
printf("%lld", PAM::count());
}