Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。
Output
多行,每行一个答案表示最少需要使用第二个机器的次数。
Sample Input
abcdcba
abacada
abcdef
Sample Output
0
2
5
HINT
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000
题解
首先跑manacher然后再跑贪心
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
struct Node {
int l, r;
} a[N];
char s[N], t[N];
int ans, tot, now, pal[N];
bool cmp(const Node &a, const Node &b) {
return a.l < b.l || (a.l == b.l && a.r < b.r);
}
void manacher() {
int len = strlen(t);
for(int i = 0; i < len; i ++)
s[++ tot] = '#', s[++ tot] = t[i];
s[0] = '+', s[++ tot] = '#', s[tot + 1] = '-';
int id = 0, mx = 0;
for(int i = 1; i <= tot; i ++) {
pal[i] = mx >= i ? min(pal[id * 2 - i], mx - i + 1) : 1;
while(s[i + pal[i]] == s[i - pal[i]]) pal[i] ++;
if(pal[i] + i - 1 > mx)
mx = pal[i] + i - 1, id = i;
a[i].l = i - pal[i] + 1, a[i].r = i + pal[i] - 1;
}
}
void clear() {
ans = tot = 0, now = 1;
memset(a, 0, sizeof(a));
memset(pal, 0, sizeof(pal));
}
int main() {
while(scanf("%s", &t) != EOF) {
clear();
manacher();
sort(a + 1, a + tot + 1, cmp);
for(int i = 1; i <= tot; i ++) {
int x = 0;
if(a[i].r <= now) continue;
for(register int j = i; j <= tot; j ++) {
if(a[j].l <= now && a[j].r >= a[x].r) x = j;
else if(a[j].l > now) break;
}
now = a[x].r, ans ++;
if(now >= tot) break;
}
printf("%d\n", ans - 1);
}
}