【题目链接】

            http://poj.org/problem?id=3974

【算法】

           解法1 :

           字符串哈希

           我们可以分别考虑奇回文子串和偶回文子串,从前往后扫描字符串,然后二分答案,检验可以用哈希

           时间复杂度 : O(TNlog(N))

           解法2

           Manacher算法

           这个算法可以在O(n)时间内求出最长回文子串,读者可以自行查阅资料,笔者不进行详细的介绍

           两种方法的效率比对

           显然,Manacher算法的复杂度是优于字符串哈希的,笔者的两份代码在POJ上的运行时间分别为4891MS和266MS

【代码】

            代码1

/*
        Algorithm : Hash
        Time Complexity : O(Tnlog(n))
*/

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXL 1000010
typedef unsigned long long ULL;
const int P = 13331;

int i,len,l,r,mid,tmp,ans,TC;
ULL f[MAXL],ha[MAXL],hb[MAXL];
char s[MAXL];
 
inline ULL getha(int l,int r)
{
        return ha[r] - ha[l-1] * f[r-l+1];
}
inline ULL gethb(int l,int r)
{
        int tmp = l;
        l = len - r + 1;
        r = len - tmp + 1;
        return hb[r] - hb[l-1] * f[r-l+1];
}

int main() 
{
        
        f[0] = 1;
        for (i = 1; i < MAXL; i++) f[i] = f[i-1] * P;
        while (scanf("%s",s+1))
        {
                len = strlen(s+1);
                if (s[1] == 'E') break;
                for (i = 1; i <= len; i++)    ha[i] = ha[i-1] * P + (s[i] - 'a' + 1);
                reverse(s+1,s+len+1);
                for (i = 1; i <= len; i++) hb[i] = hb[i-1] * P + (s[i] - 'a' + 1);
                ans = 1;
                for (i = 1; i <= len; i++)
                {
                        l = 1; r = min(i-1,len-i);    
                        tmp = 0;
                        while (l <= r)
                        {
                                mid = (l + r) >> 1;
                                if (getha(i-mid,i) == gethb(i,i+mid))
                                {
                                        tmp = mid;
                                        l = mid + 1;
                                } else r = mid - 1;
                        }
                        ans = max(ans,2*tmp+1);
                        l = 1; r = min(i,len-i);
                        tmp = 0;
                        while (l <= r)
                        {
                                mid = (l + r) >> 1;
                                if (getha(i-mid+1,i) == gethb(i+1,i+mid))
                                {
                                        tmp = mid;
                                        l = mid + 1;
                                } else r = mid - 1;
                        }
                        ans = max(ans,2*tmp);
                } 
                printf("Case %d: %d\n",++TC,ans);
        }
        
        return 0;
    
}

                代码2

 

/*
        Algorithm : Manacher
        Time Complexity : O(TN)
*/

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 1000010

int TC;
char s[MAXN<<1];

inline void Manacher()
{
        int i,len,mx = 0,pos = 0,ans = 0;
        static char tmp[MAXN<<1];    
        static int p[MAXN<<1];    
        len = strlen(s+1);
        for (i = 1; i <= len; i++) 
        {
                tmp[2*i-1] = '#';
                tmp[2*i] = s[i];
        }
        tmp[len = 2 * len + 1] = '#';
        for (i = 1; i <= len; i++)
        {
                if (mx > i) p[i] = min(p[2*pos-i],mx-i);
                else p[i] = 1;
                while (i - p[i] >= 1 && i + p[i] <= len && tmp[i-p[i]] == tmp[i+p[i]]) p[i]++;
                if (i + p[i] - 1 > mx)
                {
                        mx = i + p[i] - 1;
                        pos = i;
                }
        }
        for (i = 1; i <= len; i++) ans = max(ans,p[i]-1);
        printf("Case %d: %d\n",++TC,ans);
}

int main() 
{
        
        while (scanf("%s",s+1) != EOF)
        {
                if (s[1] == 'E') break;
                Manacher();
        }
        
        return 0;
    
}