hdu 5340 Three Palindromes(manacher)

来源:互联网 发布:java入门书籍在线阅读 编辑:程序博客网 时间:2024/05/18 21:41

题意:

给出一个字符串,能否分成三个非空回文串。

解析:

我们可以发现第一个串和第三个串,一定是最大回文串的某个串,那么Manacher 求出所有最大回文串的长度。
那么问题变成了求一个id使得1<=d<=r(i)pre[id]suf[i+d]为真。

枚举i,实际上就是问pre[ir(i)..i1]suf[i+1..i+r(i)]取反后 这两段有没有一个位置两者均为1,暴力压位即可。

总时间复杂度为O(N2/32)

my code

#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*2] = '#';        str[i*2+1] = s[i];    }    str[len*2] = '#';    str[len*2+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*2-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 pre[40005], suf[40005];int judge() {    len = strlen(s);    len2 = len * 2;    memset(pre, false, sizeof(bool)*len2);    memset(suf, false, sizeof(bool)*len2);    if (len == 3) return 1;    if (len < 3) return 0;    for (int i = 1; i <= len2; i++) {        if (p[i] - 1 == i)            pre[i + (p[i] - 1)] = true;        if (p[len2 - i] - 1 == i)            suf[len2 - i - (p[len2 - i] - 1)] = true;    }    for (int i = 1; i <= len2; i++) {        for (int j = 1; j < p[i]; j++) {            if (pre[i - j] && suf[i + j]) {                return 1;                }            }    }    return 0;}int main() {    int T;    scanf("%d", &T);    while (T--) {        scanf("%s", s);        memset(p, 0, sizeof(p));        manacher();        if (judge()) printf("Yes\n");            else printf("No\n");    }    return 0;}
0 0
原创粉丝点击