HDU 5340 Three Palindromes(Manacher)

Problem Description:

Can we divided a given string S into three nonempty palindromes?

Input:

First line contains a single integer T≤20 which denotes the number of test cases.

For each test case , there is an single line contains a string S which only consist of lowercase English letters.1≤|s|≤20000

Output:

For each case, output the "Yes" or "No" in a single line.

Sample Input:

2

abc

abaadada

Sample Output:

Yes

No

题意:判断一个字符串是否能完全分成三个回文串。

分析:一个字符串如果想要分成三个字符串,那么肯定第一个回文串的左端点肯定是第一个字符,第三个回文串的右端点肯定是最后一个字符,那么我们只需要判断中间的字符串是否是回文串就行啦。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

const int N=1e6+10;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;

typedef long long LL;

char s[N], str[N];
int r[N], k, left[N], right[N], L, R;

void Palind()
{
    int i, index = 0;

    for (i = 2; str[i] != ‘\0‘; i++)
    {
        r[i] = 1;

        if (r[index]+index > i) r[i] = min(r[2*index-i], r[index]+index-i);

        while (str[i+r[i]] == str[i-r[i]]) r[i]++;

        if (r[i]+i > r[index]+index) index = i;

        if (r[i] == 1) continue; ///半径是1的肯定是‘#’,不能统计
        if (i-r[i] == 0) left[L++] = 2*r[i]-1; ///left保存每个左端点是第一个字符的回文串的直径
        if (i+r[i] == k) right[R++] = 2*r[i]-1; ///right保存每个右端点是最后一个字符的回文串的直径
    }
}

int main ()
{
    int T, i, j, y, x, flag, len;

    scanf("%d", &T);

    while (T--)
    {
        k = 2;
        scanf("%s", s);

        memset(r, 0, sizeof(r));
        memset(str, 0, sizeof(str));
        L = R = flag = 0;

        str[0] = ‘$‘;
        str[1] = ‘#‘;

        for (i = 0; s[i] != ‘\0‘; i++)
        {
            str[k++] = s[i];
            str[k++] = ‘#‘;
        }
        str[k] = ‘\0‘;

        Palind();

        for (i = 0; i < L; i++)
        {
            for (j = 0; j < R; j++)
            {
                y = k-right[j]; ///计算右端点是最后一个字符的回文串的左端点
                if (left[i] >= y) continue; ///如果左端点是第一个字符的回文串的右端点与右端点是最后一个字符的回文串的字符重合,则跳过

                len = y-left[i]+1; ///计算中间字符的长度
                x = r[len/2+left[i]]; ///计算以中间字符中心为中心的回文串的半径
                if (x*2-1+left[i]+right[j] >= k) ///计算三个回文串的长度之和是否>=k
                {
                    flag = 1;
                    break;
                }
            }

            if (flag == 1) break;
        }

        if (flag == 1) printf("Yes\n");
        else printf("No\n");
    }

    return 0;
}
时间: 2024-10-10 00:16:26

HDU 5340 Three Palindromes(Manacher)的相关文章

HDU - 5340 Three Palindromes(manacher算法)

http://acm.hdu.edu.cn/showproblem.php?pid=5340 题意 判断是否能将字符串S分成三段非空回文串 分析 manacher预处理出前缀和后缀回文的位置, 枚举第一个回文串和第三个回文串,这样得到第二个回文串的区间,找中点,因为manacher处理后所有的回文串长度都是奇数,然后根据中点的回文半径判断中间部分是否回文即可, 复杂度o(n2).至于n2复杂度为什么能水过去..不是很懂 #include<iostream> #include<cmath&

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

hdu 5340 Three Palindromes 问题描述 判断是否能将字符串S分成三段非空回文串. 输入描述 第一行一个整数T,表示数据组数.T \leq 20T≤20 对于每一个组,仅包含一个由小写字母组成的串.1 \leq |S| \leq 200001≤∣S∣≤20000 输出描述 对于每一组,单行输出"Yes" 或 "No". 输入样例 2 abc abaadada 输出样例 Yes No 题目大意:给出一个字符串,判断,是否能将其分成三个不为空的回文

hdu 5340 Three Palindromes 【Manacher】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5340 题意:判断一个字符串能否分为三个回文串 解法:manacher枚举第一第三个,判断第二个. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #inclu

HDU 5340——Three Palindromes——————【manacher处理回文串】

Three Palindromes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1244    Accepted Submission(s): 415 Problem Description Can we divided a given string S into three nonempty palindromes? Input F

HDU 4513 吉哥系列故事——完美队形II(Manacher)

Problem Description 吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形: 1.挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的: 2.左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意: 3.从左到中间那

HDU Hotaru&#39;s problem(Manacher算法+贪心)

manacher算法详见 http://blog.csdn.net/u014664226/article/details/47428293 题意:给一个序列,让求其最大子序列,这个子序列由三段组成,第一段和第二段对称,第一段和第三段一样. 思路:首先利用Manacher算法求出以任意两个相邻元素为中心的回文串长度,用a[i]表示i-1,i为中心的回文串长度的一半, 那么问题就转化成了求最大的x,使得a[i]>=x,a[i+x]>=x,这一步可以贪心来做. 将a[i]从大到小排序(间接排序保留

【SPOJ】NUMOFPAL - Number of Palindromes(Manacher,回文树)

[SPOJ]NUMOFPAL - Number of Palindromes(Manacher,回文树) 题面 洛谷 求一个串中包含几个回文串 题解 Manacher傻逼题 只是用回文树写写而已.. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<

hdu3294Girls&#39; research(manacher)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3294 题目不难,感觉输出比较麻烦. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=2000010; 6 char s[maxn<<1]; 7 int r[maxn<<1]; 8 char ans[

HDU 1045 - Fire Net (最大独立集)

题意:给你一个正方形棋盘.每个棋子可以直线攻击,除非隔着石头.现在要求所有棋子都不互相攻击,问最多可以放多少个棋子. 这个题可以用搜索来做.每个棋子考虑放与不放两种情况,然后再判断是否能互相攻击来剪枝.最后取可以放置的最大值. 这里我转化成求最大独立集来做. 首先将每个空地编号,对于每个空地,与该位置可以攻击到的空地连边.找最多的空地使得不互相攻击,即求该图的最大独立集.与搜索做法基本一致,但是说法略有不同. 1 #include<iostream> 2 #include<cstring