HDU5340——Manacher算法——Three Palindromes

http://acm.hdu.edu.cn/showproblem.php?pid=5340

/*
Manacher算法:O(n) 实现最长回文子串
算法实现:
先向原字符串中插入一个原来串不存在的字符,一般用‘#‘,再O(n)遍历一遍,用一个数组p[i]来记录以str[i]为中心的回文半径(注意str[i]是新串,长度为2*len+1),mx记录当前已有的回文最长到的位置,假定当前为i,j为i前面已经计算过的数,id为最长的回文的中心,那么可以得到一个方程 p[i] = min(p[2*id-i],mx - i),p[2*id-i]与p[i]是关于id对称的,那么p[i]的回文长度就是p[2*id-1]的回文长度,可是如果p[i]的长度超过了p[id]的mx,那么右边的就不确定了,然后再向外扩展

*/
/************************************************
* Author        :Powatr
* Created Time  :2015-8-12 13:11:42
* File Name     :Manacher.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

int pre1[MAXN], pre2[MAXN];
int p[MAXN];
char s[MAXN];
char str[MAXN];
int n;
void inti()
{
    memset(str, 0, sizeof(str));
    memset(p, 0, sizeof(p));
    memset(pre1, 0, sizeof(pre1));
    memset(pre2, 0, sizeof(pre2));
     n = strlen(s+1);
    str[0] = ‘$‘;
     for(int i = 1; i <= n; i++){
         str[i*2-1] = ‘#‘;
         str[i*2] = s[i];
     }
     n = 2*n+1;
     str[n] = ‘#‘;str[n+1] = ‘\0‘;
}

void Manacher()
{
    int mx = 0, id;
    for(int i = 1; i <= n; i++){
            if(mx > i) p[i] = min(p[2*id-i], mx-i);
            else p[i] = 1;
            for(; str[i+p[i]] == str[i-p[i]]; p[i]++);
            if(p[i] + i > mx){
                mx = p[i] + i;
                id = i;
            }
    }
}

bool check()
{
    int cout1 = 0, cout2 = 0;
    for(int i = 1; i <= n; i++){
        if(p[i]  == i && i != 1){// printf("%d ", i);
            pre1[++cout1] = i;}
        if(i + p[i] - 1 == n  && i != n) pre2[++cout2] = i;
    }
    int l, r, mid;
    for(int i = 1; i <= cout1; i++){
        for(int j = 1; j <= cout2; j++){
            l = pre1[i] + p[pre1[i]] ;
            r = pre2[j] - p[pre2[j]] ;
            if(l > r) continue;
            mid = l + r >> 1;
            if(p[mid] > (r - l + 1 >> 1)){//这边是大于,因为p[mid]包含了自己
                return true;
            }
        }
    }
    return false;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%s", s+1);
        n = strlen(s+1);
        if(n < 3) {printf("No\n");continue;}
        inti();
        Manacher();
        if(check()) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

  

时间: 2024-10-31 11:16:44

HDU5340——Manacher算法——Three Palindromes的相关文章

hdu5340—Three Palindromes—(Manacher算法)——回文子串

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

HDU 5340-Three Palindromes(Manacher算法)

题目地址:HDU 5340 题意:问是否能将字符串str分解为三段非空的回文串. 思路:我们根据Manacher算法对字符串进行处理,处理过程中产生的P数组,我们可以得到两个数组first和last. first存储的是第一个回文串的半径可能值. last存储的是第三个回文串的半径可能值. 根据first和last我们可以枚举第一个回文串和第三个回文串,然后根据半径找出第二个回文串的初始位置和结束位置.然后计算出第二个回文串的中点: 1.如果ll>rr,则第二个字符串的长度为负数,pass 2.

HDU 3068 最长回文 (manacher算法)

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9188    Accepted Submission(s): 3159 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

最长回文---hdu3068 (回文串 manacher 算法模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意很清楚:就是求一个串s的子串中最长回文串的长度:这类题用到了manacher算法 manacher算法(复制大神的解释): 定义数组p[i]表示以i为中心的(包含i这个字符)回文串半径长 将字符串s从前扫到后for(int i=0;i<strlen(s);++i)来计算p[i],则最大的p[i]就是最长回文串长度,则问题是如何去求p[i]? 由于s是从前扫到后的,所以需要计算p[i]时一定

LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2

https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhorizen/article/details/6629268 class Solution { public: string longestPalindrome(string s) { char ch[2001];int p[2001]; ch[2*s.size()] = 0; for(int i =

Manacher算法----最长回文子串

题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的.同时,奇数和偶数长度还要分别考虑. Manacher算法可以解决上述问题,并在O(n)时间复杂度内求出结果.下面我们来看一下Manacher算法. 首先,为了处理奇偶的问题,在每个字符的两边都插入一个特殊的符号,这样所有的奇数或偶数长度都转换为奇数长度.比

浅谈Manacher算法与扩展KMP之间的联系

首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解,网上解法颇多,时间复杂度也不尽相同,这里列述几种常见的解法. 解法一 通过枚举S的子串,然后判断该子串是否为回文,由于S的子串个数大约为,加上每次判断需要的时间,所以总的时间复杂度为,空间复杂度为. bool check(string &S, int left, int right) { while (left < right && S[left]

[hiho 01]最长回文子串、Manacher算法

题目描述 - 基础方法:枚举子串,判断是否为回文串. - 改进:枚举中间位置,向两侧拓展. - 再改进:利用以前的信息,使得不用每个新位置都从长度1开始拓展. - 优化:将字符串预处理为奇数长度以避免考虑条件分支. - 再优化:开头加入特殊字符避免考虑边界. Manacher 算法: id 是中心点,mx 是其边界.P[i] 表示以 i 为中心的最长回文子串的折半长度. 只要 i < mx, 以 i 为中心的回文子串就可以不必从长度1开始找,而从min{P[j], mx - i}开始(其中j为i

hdu-3068 最长回文 【Manacher算法】

Manacher算法学习资料:http://blog.csdn.net/dyx404514/article/details/42061017 最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9282    Accepted Submission(s): 3194 Problem Description 给出一个只由小写英文字符