hdu 5340 Three Palindromes
问题描述
判断是否能将字符串S分成三段非空回文串。
输入描述
第一行一个整数T,表示数据组数。T \leq 20T≤20
对于每一个组,仅包含一个由小写字母组成的串。1 \leq |S| \leq 200001≤∣S∣≤20000
输出描述
对于每一组,单行输出”Yes” 或 “No”。
输入样例
2
abc
abaadada
输出样例
Yes
No
题目大意:给出一个字符串,判断,是否能将其分成三个不为空的回文字符串。
解题思路:先用manacher算法求出以每一点为中心可以扩张的最长的回文串范围。然后可以求出两个数组pre[i]和pos[i],记录的是在i点做切割,可以使i之前的或之后的子字符串,成为回文字符串。求出pre和pos数组之后,遍历中间那一段字符串的中心点,每找到一个中心点,以它为中心向两边扩张 (1 < a < p[i] - 1)当pre[i - a]和pos[i + a]都被标记,则该切割是有效的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20005;
char str[N<<1], s[N];
int p[N<<1], len, len2;
void manacher() {
len = strlen(s);
for(int i = 0; i < len; i++) {
str[i<<1] = ‘#‘;
str[(i<<1) + 1] = s[i];
}
str[len<<1] = ‘#‘;
str[(len<<1) + 1] = ‘\0‘;
len = strlen(str);
int maxp = 0, id = 0;
for(int i = 0; i < len; i++) {
if(maxp > i) p[i] = min(maxp - i, p[(id<<1) - i]);
else p[i] = 1;
for(;str[i - p[i]] == str[i + p[i]] && i + p[i] < len && i - p[i] >= 0; p[i]++);
if(i + p[i] > maxp) {
maxp = p[i] + i;
id = i;
}
}
}
bool A[40005], B[40005];
bool mark() {
len = strlen(s);
len2 = (len<<1) + 1;
memset(A, 0, len2);
memset(B, 0, len2);
if (len == 3) return true;
if (len < 3) return false;
for (int i = 1; i < len2; i++) {
if (p[i] - 1 == i) A[i + (p[i] - 1)] = true;
if (p[len2 - 1 - i] - 1 == i) B[len2 - 1 - i - (p[len2 - 1 - i] - 1)] = true;
}
for (int i = 1; i < len2 - 1; i++) {
for (int j = 1; j < p[i]; j++) {
if (A[i - j] & B[i + j]) {
return true;
}
}
}
return false;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%s", s);
manacher();
if (mark()) {
printf("Yes\n");
} else printf("No\n");
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许也可以转载,不过要注明出处哦。
时间: 2024-11-02 08:43:41