题目

July 8, 2021 · View on GitHub

如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。

输入格式
输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。

输入以一个以字符串 END 开头的行表示输入终止。

输出格式
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

每个输出占一行。

输入样例:

abcbabcbabcba
abacacbaaaab
END

输出样例:

Case 1: 13
Case 2: 6

参考答案

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>

#define boost ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fo(v,a,b) for(int v=(a); v<=(b); v++)
#define fr(v,a,b) for(int v=(a); v>=(b); v--)
#define rng(v,a,b) for(int v=(a); v<(b); v++)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<typename T> T& chmax(T& a, T b) { a = a > b ? a : b; return a;}
template<typename T> T& chmin(T& a, T b) { a = a < b ? a : b; return a;}
const int maxn=1e6+6,P=131;
char s[maxn],a[maxn*2];
ull H1[maxn*2],H2[maxn*2],g[maxn*2];
int main()
{
    int T=0;
    while(cin >> (s+1) && strcmp(s+1, "END")) {
        cout << "Case " << ++T << ": ";
        int len = strlen(s+1), tl=0;
        a[++tl] = '#';
        fo(i,1,len) {
            a[++tl] = s[i]; a[++tl] = '#';
        }
        a[tl+1] = '\0'; len=tl;

        g[0] = 1;
        fo(i,1,len) {
            H1[i] = H1[i-1]*P+a[i]; g[i] = g[i-1]*P;
        }
        fr(i,len,1) H2[i] = H2[i+1]*P+a[i];

        int ans=0,l;
        fo(i,1,len) {
            l=ans;
            if(i+l>=len || i-l<1) break;
            if(H1[i+l]-H1[i-1]*g[l+1] != H2[i-l]-H2[i+1]*g[l+1]) continue;
            while(a[i+l+1] == a[i-l-1] && i+l+1<=len && i-l-1>0) l++;
            chmax(ans,l);
        }
        cout << ans << '\n';
    }
    return 0;
}