地址 https://www.acwing.com/problem/content/141/
如果一个字符串正着读和倒着读是一样的,则称它是回文的。 给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。 输入格式 输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。 输入以一个以字符串 END 开头的行表示输入终止。 输出格式 对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。 每个输出占一行。 输入样例: abcbabcbabcba abacacbaaaab END 输出样例: Case 1: 13 Case 2: 6
解答
那么计算出字符串的正序和逆序哈希值
以每个点展开向两旁扩展 获取哈希值 如果每个点两边的哈希值一致 那么它就是回文串记录回文串长度,返回最大值即可.
回文判断有aba和aabb两种,中间填充符号就可以直接划分为一种判断方式了
比如转化为 a#b#a a#a#b#b
考虑到数据量较大 判断回文串的长度使用二分比遍历要快,否则会tle
// Ac139.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <algorithm> #include <memory.h> using namespace std; /* 如果一个字符串正着读和倒着读是一样的,则称它是回文的。 给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。 输入格式 输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。 输入以一个以字符串 END 开头的行表示输入终止。 输出格式 对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。 每个输出占一行。 输入样例: abcbabcbabcba abacacbaaaab END 输出样例: Case 1: 13 Case 2: 6 */ const int N = 2001000; //const int N = 1001000; unsigned long long lh[N]; unsigned long long rh[N]; unsigned long long p[N]; const int base = 131; char str[N]; char cpStr[N]; int ans = 1; unsigned long long GetHashVl(unsigned long long h[N], int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; } unsigned long long GetHashVr(unsigned long long h[N], int l, int r) { return h[l] - h[r + 1] * p[r - l + 1]; } int GetRealLen(int len, char c) { if (c == '#') { if (len % 2 == 0) return len; else return (len / 2 + 1) * 2; } else { if (len % 2 == 0) return len + 1; else return (len / 2) * 2 + 1; } } int main() { int idx = 1; while (1) { ans = 1; memset(cpStr, 0, sizeof(cpStr)); memset(lh, 0, sizeof lh); memset(rh, 0, sizeof lh); scanf("%s", str + 1); if (strcmp(str + 1, "END") == 0) { break; } int len = strlen(str + 1); memset(cpStr, 0, sizeof(cpStr)); for (int i = 0; i < len; i++) { cpStr[i * 2 + 1] = str[i + 1]; cpStr[i * 2 + 2] = '#'; } //计算正向逆向的哈希值的 然后遍历字节得到以遍历点为中心的最长回文长度 len = strlen(cpStr + 1) - 1; cpStr[len + 1] = '\0'; p[0] = 1; for (int i = 1; i <= len; i++) { lh[i] = lh[i - 1] * base + cpStr[i] - 'a' + 1; int j = len - i + 1; rh[j] = rh[j + 1] * base + cpStr[j] - 'a' + 1; p[i] = p[i - 1] * base; } for (int i = 1; i <= len; i++) { int r = min(i - 1, len - i); int l = 0; while (l < r) { int mid = (l + r+1) >> 1; if (GetHashVl(lh, i - mid, i) != GetHashVr(rh, i, i + mid)) { r = mid-1; } else { l = mid ; } } int realLen = GetRealLen(l, cpStr[i]); ans = max(ans, realLen); } printf("Case %d: %d\n", idx++, ans); } return 0; }
我的视频题解空间