《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度
2021/5/18 14:28:00
本文主要是介绍《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
地址 https://www.acwing.com/problem/content/141/
如果一个字符串正着读和倒着读是一样的,则称它是回文的。 给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。 输入格式 输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。 输入以一个以字符串 END 开头的行表示输入终止。 输出格式 对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。 每个输出占一行。 输入样例: abcbabcbabcba abacacbaaaab END 输出样例: Case 1: 13 Case 2: 6
解答
- 前置知识 字符串哈希
对于一个长度为len的字符串str 可以使用一个数组 unsigned long long hashV[N] 来记录
1~n的 字符串的哈希值 hashV[i]=hashV[i-1]x131 + str[i]-'a'+1;
对于a到b的区间字符串的哈希值就是 hashV[b] - hashV[a]x131^(b-a+1)
那么计算出字符串的正序和逆序哈希值
以每个点展开向两旁扩展 获取哈希值 如果每个点两边的哈希值一致 那么它就是回文串记录回文串长度,返回最大值即可.
-
回文判断有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; }
我的视频题解空间
这篇关于《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享