[POJ 3974] Palindrome (字符串哈希+二分)

原创 2016年08月30日 21:05:59

链接

POJ 3974


题意

给出字符串,求其最长回文子串的长度。


思路

该题目可用manacher算法在O(n)时间内解决。
最长回文子串,也是子串+长度类型的问题,此处使用字符串哈希+二分解决。
对字符串进行正序倒序两次哈希,之后二分长度,对每个长度len枚举子串的哈希值,判断相同位置的子串正逆序哈希值是否相同,相同则代表为回文串。
复杂度O(n*log(n))。


代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef unsigned long long ulint;
const ulint seed = 30007uLL;
#define maxn 1010000
ulint H[maxn], P[maxn], xp[maxn];
char s[maxn];
int N;

void initHash()
{
    H[0] = s[0];
    for(int i = 1; i < N; i++)
        H[i] = H[i - 1]*seed + s[i];

    P[N-1] = s[N-1];
    for(int i = N-2; i >= 0; i--)
        P[i] = P[i + 1]*seed + s[i];
}

ulint askHash(int l, int r)
{
    if(l == 0) return H[r];
    return H[r] - H[l - 1]*xp[r - l + 1];
}

ulint askP(int l, int r)
{
    if(r == N-1) return P[l];
    return P[l] - P[r + 1]*xp[r - l + 1];
}


bool check(int len)
{
    //cout << "len = " << len << endl;
    ulint ht, pt;

    for(int i = 0, l, r; i + len - 1 < N; i++)
    {
        l = i, r = i + len - 1;
        ht = askHash(l, r);
        pt = askP(l, r);

        //cout << ht << " " << pt << endl;

        if(ht == pt) return true;
    }

    return false;
}


int main()
{
    xp[0] = 1;
    for(int i = 1; i < maxn; i++)
    {
        xp[i] = xp[i-1] * seed;
    }

    int kase = 0;
    while(~scanf("%s", &s))
    {
        if(string(s) == string("END"))
            break;

        N = strlen(s);
        for(int i = 0; i < N; i++)
        {
            s[i] = s[i] - 'a' + 1;
        }

        initHash();
/*
        for(int i = 0; i < N; i++)
        {
            cout << askHash(i, i) << " " << askP(i, i) << endl;
        }
*/


        vector<int> dexod, dexev;
        for(int i = 1; i <= N; i++)
        {
            if(i % 2) dexod.push_back(i);
            else dexev.push_back(i);
        }

        int ans = 0, l = 0, r = dexod.size() - 1, m;
        while(l <= r)
        {
            m = (l + r) >> 1;

            if(check(dexod[m]))
            {
                l = m + 1;
                ans = dexod[m];
            }
            else r = m - 1;
        }

        l = 0, r = dexev.size() - 1;
        while(l <= r)
        {
            m = (l + r) >> 1;

            if(check(dexev[m]))
            {
                l = m + 1;
                ans = max(ans, dexev[m]);
            }
            else r = m - 1;
        }

        printf("Case %d: ", ++kase);
        cout << ans << endl;
    }
    return 0;
}
版权声明:想转就转吧,反正也是人人都会的东西:-(

相关文章推荐

字符串-POJ3974-Palindrome

PalindromeTime Limit: 15000MS Memory Limit: 65536KDescriptionAndy the smart computer science stu...

poj3974 Palindrome [字符串回文]

本题的题意是给你一个字符串 让你判断这个字符串中最长的回文子串的长度 嗯 这题可以用O(n)的时间复杂度的manacher算法来处理 manacher在很久前就知道了,但是只是知道了怎么去构造但是还没...

POJ3974 Palindrome 解题报告【字符串】【Manacher】

POJ 3974
  • theljt
  • theljt
  • 2017年07月28日 10:06
  • 67

POJ:3974 Palindrome (Manacher算法)

Manacher算法:在O(n)的时间内求得最长回文子串。   在这里简单说一下这个算法。 首先在原字符串s之间加入一个特殊字符(原串中没有的)#作为标记构造一个新串ss。这样做可以其实可以把最长回文...
  • kkkwjx
  • kkkwjx
  • 2013年09月07日 21:18
  • 575

poj3974:Palindrome(manacher模板)

DescriptionAndy the smart computer science student was attending an algorithms class when the profes...

POJ 3974 Palindrome 回文串

求最长回文串  由于数据大  需要O(n)的算法  Manacher算法 这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地...

POJ 3974 Palindrome(Manacher)

Palindrome Description Andy the smart computer science student was attending an algorithms class...

hdu3068 最长回文 poj3974 Palindrome(Manacher算法)

#include #include #include #include using namespace std; char a[110005],str[220010]; int p[220010]; ...
  • turbo_7
  • turbo_7
  • 2013年05月21日 23:56
  • 407

POJ-3974-Palindrome- Manacher 马拉车算法(On寻找最长回文串)

http://poj.org/problem?id=3974 马拉车算法的讲解,这个地方讲得很详细:http://www.cnblogs.com/grandyang/p/4475985.html ...
  • viphong
  • viphong
  • 2016年01月08日 09:51
  • 456

【POJ3974】Palindrome Manacher、模板题 裸题

Manacher裸题,模板题
  • Vmurder
  • Vmurder
  • 2014年12月24日 08:56
  • 995
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[POJ 3974] Palindrome (字符串哈希+二分)
举报原因:
原因补充:

(最多只允许输入30个字)