hdu 5340 Three Palindromes

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5340

题目大意:给你一个全部都是小写英文字母的字符串 s,|s|<20000 问你能不能分成3个非空的回文字串。

解题思路:Manacher算法O(n)求出以每个点为中心的最大的回文的半径,然后暴力枚举分割位置,验证!

我之前用hash写过一发,一直TLE,发现是我的hash写挫了,本来可以O(n)的预处理 ,O(1)的查询,但是我写成了O(n)的预处理,O(logn)的查询,然后一直TLE。

最后还是问师兄,才知道怎么写O(1)的查询,我真是太弱了。。。

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 20005;

char str[N], nstr[N << 1];
int R[N << 1];
int len, nlen;

void Manacher()
{
    nstr[0] = '#';
    nlen = 1;
    for(int i = 0; i < len; i++)
    {
        nstr[nlen++] = str[i];
        nstr[nlen++] = '*';
    }
    nstr[nlen++] = '#';
    int p(0);
    for(int i = 1; i < nlen; i++)
    {
        if(2 * p - i >= 0) R[i] = min(p + R[p] - i, R[2 * p - i]);
        else R[i] = p + R[p] - i;
        R[i] = max(R[i], 0);
        while(i + R[i] + 1 < nlen && i - R[i] - 1 >= 0 && nstr[i + R[i] + 1] == nstr[i - R[i] - 1]) R[i]++;
        if(R[i] > R[p]) p = i;
    }
}

int pre[N], lp;
int suf[N], ls;

bool check(int l, int r)
{
    int mid = (l + r) >> 1;
    if(R[mid] >= mid - l) return true;
    return false;
}

int main()
{
#ifdef PKWV
//    freopen("in.in", "r", stdin);
#endif // PKWV
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%s", str);
        len = strlen(str);
        Manacher();
        lp = 0, ls = 0;
        for(int i = len - 1; i >= 0; i--)
        {
            int p = i * 2 + 1;
            if(check(1,p)) pre[lp++]=i;
            if(check(p,len*2-1)) suf[ls++]=i;
        }
        bool ok(false);
        for(int i = 0; i < lp; i++)
        {
            for(int j = 0; !ok && j < ls && pre[i] + 1 < suf[j]; j++)
            {
                if(check((pre[i] + 1)<< 1 | 1, (suf[j] - 1) << 1 | 1))
                {
                    ok = true;
                    break;
                }
            }
        }
        if(ok) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u014076176/article/details/47207115