【YbtOJ高效进阶 哈希-2】回文子串

链接

YbtOJ高效进阶 哈希-2

题目描述

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

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

样例输入

abcbabcbabcba
abacacbaaaab
END

样例输出

Case 1: 13 
Case 2: 6

思路

正反两遍求出hash值,然后枚举点向两边二分求出最大长度

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#define ull unsigned long long
using namespace std;
int l, r, mid, t, len, ans;
ull c[1000050], z[1000050], f[1000050];
char s[1000050];
void work() {
    
    
    memset(z, 0, sizeof(z));
    memset(f, 0, sizeof(f));
    ans = 1;
    for (int i = 0; i < len; ++i) z[i + 1] = z[i] * 131 + s[i];
    for (int i = len; i > 0; --i) f[i] = f[i + 1] * 131 + s[i - 1];
    for (int i = 1; i <= len; ++i) {
    
    
        l = 0;
        r = (len >> 1) + 1;
        while (r >= l) {
    
    
            mid = (l + r) >> 1;
            if (i - mid <= 0 || i + mid > len)
                r = mid - 1;
            else if (z[i] - z[i - mid - 1] * c[mid + 1] == f[i] - f[i + mid + 1] * c[mid + 1]) {
    
    
                ans = max(ans, mid * 2 + 1);
                l = mid + 1;
            } else
                r = mid - 1;
        }
        l = 0;
        r = (len >> 1) + 1;
        if (z[i] - z[i - 1] * 131 == f[i + 1] - f[i + 2] * 131)
            ans = max(ans, 2);
        while (r >= l) {
    
    
            mid = (l + r) >> 1;
            if (mid == 0)
                break;
            if (i - mid + 1 <= 0 || i + mid > len)
                r = mid - 1;
            else if (z[i] - z[i - mid] * c[mid] == f[i + 1] - f[i + mid + 1] * c[mid]) {
    
    
                ans = max(ans, mid * 2);
                l = mid + 1;
            } else
                r = mid - 1;
        }
    }
    printf("Case %d: %d\n", t, ans);
}
int main() {
    
    
    char cc;
    c[0] = 1;
    for (int i = 1; i <= 1000000; ++i) c[i] = c[i - 1] * 131;
    cc = getchar();
    len = 0;
    while (cc != ' ' && cc != '\n') {
    
    
        s[len] = cc;
        cc = getchar();
        ++len;
    }
    t = 1;
    while (s[0] != 'E') {
    
    
        work();
        ++t;
        cc = getchar();
        len = 0;
        while (cc != ' ' && cc != '\n') {
    
    
            s[len] = cc;
            if (cc >= 'A' && cc <= 'Z')
                return 0;
            cc = getchar();
            ++len;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/114853207