HDU 5371 Hotaru's problem Manacher+尺取法
2015-08-13 10:14
162 查看
题意:给你一个序列,求最长的两段回文子串,要求他们共用中间的一半。
思路:利用Manacher求出p[i]表示的当前位置的最长回文串长度,然后把每一个长度大于等于2的回文串的左区间和右区间分别放到两个数组里面,由于做manacher时添加了特殊的数字,所以处理的时候稍微注意一下。
然后把左右区间按照左端点排序,接着根据尺取法来找答案中的那一段重合的部分。对于每一段右区间R[i]而言,只有L[j].right<=R[i].right && L[j].left<=R[i].right 就是有效的,对于这样的情况所得到的有效值就是L[j].right-R[i].left+1, 当然,当L[j].left>R[i].right时,就不能够再处理R[i]了,而是去处理R[i+1]。
思路:利用Manacher求出p[i]表示的当前位置的最长回文串长度,然后把每一个长度大于等于2的回文串的左区间和右区间分别放到两个数组里面,由于做manacher时添加了特殊的数字,所以处理的时候稍微注意一下。
然后把左右区间按照左端点排序,接着根据尺取法来找答案中的那一段重合的部分。对于每一段右区间R[i]而言,只有L[j].right<=R[i].right && L[j].left<=R[i].right 就是有效的,对于这样的情况所得到的有效值就是L[j].right-R[i].left+1, 当然,当L[j].left>R[i].right时,就不能够再处理R[i]了,而是去处理R[i+1]。
#include <iostream> #include <cstdio> #include <algorithm> #define LL long long #define MAXN 100005 using namespace std; int n; LL s[MAXN * 3]; int p[MAXN]; int f[MAXN]; int m; struct Node{ int left, right; int mm; Node(int left = 0, int right = 0):left(left), right(right){ mm = right - left + 1; }; bool operator < (const Node & b) const{ return left < b.left; } }; vector<Node> L, R; void manacher(){ int res = 0, id = 0; for(int i = 1; i <= m; i++) { if(res > i){ p[i] = min(p[2 * id - i], res - i); } else{ p[i] = 1; } //p[i] = mx > i? min(mp[2*id-i], mx-i): 1; while(s[i + p[i]] == s[i - p[i]]){ p[i]++; } //while(s[i+mp[i]] == s[i-mp[i]]) mp[i]++; if(i + p[i] > res) { res = i + p[i]; id = i; } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // OPEN_FILE int T; scanf("%d", &T); int cas = 1; while(T--){ scanf("%d", &n); // char ch; m = 1; s[m++] = -2; s[m++] = -1; //LL x; for(int i = 0; i < n; i++){ scanf("%I64d", &s[m++]); s[m++] = -1; } s[m++] = -2; m--; manacher(); L.clear(); R.clear(); for(int i = 4; i <= m; i += 2){ if(s[i] != -1 || p[i] == 1) continue; int x = (i / 2) - 1; int y = x - ((p[i] - 1) / 2) + 1; L.push_back(Node(y, x)); x++; y = x + ((p[i] - 1) / 2) - 1; R.push_back(Node(x, y)); //printf("%d ", p[i] -1); } sort(L.begin(), L.end()); sort(R.begin(), R.end()); /*for(int i = 0; i < R.size(); i++){ printf("%d %d\n", R[i].left, R[i].right); }*/ int t = 0; int ans = 0; for(int i = 0; i < R.size(); i++){ while(t < L.size() && L[t].left <= R[i].left){ if(R[i].left <= L[t].right && L[t].right <= R[i].right){ ans = max(ans, L[t].right - R[i].left + 1); } t++; } } printf("Case #%d: %d\n", cas++, ans * 3); } }
相关文章推荐
- URL编码与解码
- Linux平台块设备到字符设备(裸设备)的三种映射方式(转载)
- 图论基础UVA10047
- updatepanel更新dropdownlist后其css样式失效的解决方案
- poj2976 二分最大平均值
- 解决was启动缓慢 超时问题
- 【leetcode每日一题】NO206.Reverse Linked List
- Android性能优化典范(二)
- gravity、layout_gravity及orientation
- UNIX网络编程卷一:第十六章 非阻塞I/O
- 类找不到问题追踪及分析
- sql的count()函数,php怎么取他的值
- Struts2动态方法调用
- RadioButton不能切换问题
- 从配置文件里读取配置信息
- 《招聘一个靠谱的iOS》面试题参考答案(上)
- 《android---获取值AndroidManifest.xml中meta-data的value》
- scp命令的实际应用
- 统计数n阶乘中0的位数
- SpringMVC基于代码的配置方式(零配置,无web.xml)