hdu 5340 Three Palindromes(字符串处理+ 回文)

26 篇文章 0 订阅
12 篇文章 0 订阅
本文提供了一种使用Manacher算法解决的问题,即判断一个字符串是否能够被划分为三个非空的回文子串。通过构建扩展后的字符串并应用Manacher算法求出最长回文子串的范围,进一步利用两个数组记录切割点,实现有效切割的判断。
摘要由CSDN通过智能技术生成

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值