hdu 5340 Manachers + 枚举
来源:互联网 发布:淘宝冻结账户怎么解冻 编辑:程序博客网 时间:2024/05/24 06:45
题意:给你一个字符串问能否拆分为三个回文字符串?能就输出yes,否则输出no。
知识补充:
最长回文子串算法(Manacher算法):
求解最长回文子串的线性时间复杂度算法,主要是通过中心扩展的方法极大地避免了重复计算。实现如下:
- 为了避免对字符串奇偶数的讨论,先对字符串做预处理如下:
规则为在字符间和两边插入'#'字符,为了避免越界处理,最两边插入'^'和'$'字符。原本字符串为:asd预处理后为:^#a#s#d#$
- 然后实现部分:
设置两个变量:c 和 r,表示当前最长回文字符串的中心和边界。数组p[max],p[i]表示以i为中心的回文字符串的长度
之后对字符串从左向右处理,有更长的回文字符串就更新c 和 r。这是有如下结论:对于以i为中心的字符串,如果i < r,那么就有:p[i] >= min(p[2 * c - i], r - i)。然后再进行扩展。即可
根据实现后得到的p数组和字符串的对应关系:#a#s#s#d#010121010
贴Manacher算法的模板:
Manacher算法: // 将S转换成T的预处理// 比如,S = "abba", T = "^#a#b#b#a#$"// ^和$符号用来表示开始和结束,并且避免边界检查。string preProcess(string s){ int n = s.length(); if (n == 0) return "^$"; string ret = "^"; for (int i = 0; i < n; i++) ret += "#" + s.substr(i, 1); ret += "#$"; return ret;}string longestPalindrome(string s){ string T = preProcess(s); int n = T.length(); int* P = new int[n]; int C = 0, R = 0; for (int i = 1; i < n - 1; i++) { int i_mirror = 2 * C - i; // 等于i' = C - (i-C) P[i] = (R > i) ? min(R-i, P[i_mirror]) : 0; // 尝试扩展中心为i的回文 while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) P[i]++; // 如果中心为i的回文超越了R,根据已扩展的回文来调整中心 if (i + P[i] > R) { C = i; R = i + P[i]; } } // 找出P中的最大值 int maxLen = 0; int centerIndex = 0; for (int i = 1; i < n-1; i++) { if (P[i] > maxLen) { maxLen = P[i]; centerIndex = i; } } delete[] P; //返回最大回文子串 return s.substr((centerIndex - 1 - maxLen)/2, maxLen);}
###这道题的思路:
- 先用Manacher算法处理字符串,把以左端点为起点的回文子串的右端点加入到a数组中,把以右端点为终点的回文子串的左端点加入到b数组中(这里充分利用了Manacher算法处理之后得到的p数组,根据p[i]可以变换出,以i为中心的回文字符串在原串中的起点和终点)。然后枚举左边是a[i]结尾的字符串,和右边是b[j]开始的字符串,再由p数组判断他们中间的那个字符串是否是回文串即可。
- 可以说这个题是Manacher算法的变形,只有充分理解p数组的由来,才可能知道它具有的变形能力。
- 编码时间花费了很久,在动手写代码之前一定要已经思考的非常透彻,毫无逻辑缺陷再动手,这样效率是最高的。
Code:
#include <iostream>#include <cstdio>#include <string>#include <algorithm>#include <set>#include <map>#include <vector>#include <queue>#include <iterator>#include <cmath>#include <cstring>#include <cstdlib>using namespace std;typedef long long LL;const int INF = 0x3fffffff, M = 10009;vector<int> a, b, p;string preprocess(string s){ string ret = "^"; for (int i = 0; i < s.size(); i++) { ret += "#"; ret += s[i]; } ret += "#$"; return ret;}vector<int> Manacher(string t){ vector<int> p; int R = 0, z = 0; for (int i = 1; i < t.size() - 1; i++) { p.push_back(R > i ? min(R - i, p[2 * z - i - 1]) : 0); while (t[i + p [i - 1] + 1] == t[i - p[i - 1] - 1]) p[i - 1]++; if (p[i - 1] + i > R) { z = i; R = p[i - 1] + i; } if (p[i - 1] >= 1) { int l = (i - 1 - p[i - 1]) / 2+ 1; int r = (i - 1+ p[i - 1]) / 2; if (l == 1) a.push_back(r); if (r == (t.size() - 3) / 2) b.push_back(l); } } return p;}bool hw(int x, int y){ int temp = y - x - 1; if (temp <= 0) return false; if ( p[((x * 2) - 1 + (y * 2) - 1) / 2] >= temp && (p[((x * 2) - 1 + (y * 2) - 1) / 2] - temp) % 2 == 0) return true; return false;}int main(void){ int t; cin >> t; while (t--) { a.clear(); b.clear(); p.clear(); string s; cin >> s; //for (int i = 0 ; i < 100000; i++) s += "as"; bool ans = false; if (s. size() < 3) { cout << "No" << endl; continue; } string T = preprocess(s); p = Manacher(T); //for (int i = 0; i < p.size() ; i++) cout << p[i] << " "; for (int i = 0; i < a.size(); i++) { for (int j = 0; j < b.size(); j++) { if (a[i] < b[j]) { int x = a[i]; int y = b[j]; if (hw(x, y)) { ans = true; goto l1; } } } }l1: if (ans) cout << "Yes" << endl; else cout << "No" << endl; } return 0;}
0 0
- hdu 5340 Manachers + 枚举
- hdu 5340(manacher+枚举)
- hdu 3332 暴力枚举
- hdu 4007 枚举 Dave
- hdu 4068 枚举 SanguoSHA
- hdu 1015 Safecracker(枚举)
- hdu 1087 枚举+DP
- hdu 1158 枚举+DP
- hdu-1425(排序||枚举)
- HDU 4353 枚举
- HDU 3823 暴力枚举
- HDU 4380 预处理枚举
- hdu 4334 Trouble 枚举。。。。
- hdu 2208 DFS枚举
- HDU 3118 Arbiter(枚举)
- hdu 4152 dfs 枚举
- hdu 1015 Safecracker 枚举
- hdu 1015 枚举
- android中写文件到内部存储中
- leetcode Course Schedule
- Lua快速排序算法+代码
- 取石子游戏
- pyhton_学习笔记0804
- hdu 5340 Manachers + 枚举
- H5+写文件
- leetcode——Count Primes
- nginx支持ssl简介
- 应聘中高级工程师准备
- android 矩形布局
- 比特币钱包应用breadwallet源码iOS版
- 博弈知识汇总
- 使用Spring的jdbcTemplate进一步简化JDBC操作