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] = '';
}

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
");continue;}
        inti();
        Manacher();
        if(check()) printf("Yes
");
        else printf("No
");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/zero-begin/p/4724658.html