[BZOJ2342] [Shoi2011]双倍回文(manacher)
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ2342] [Shoi2011]双倍回文(manacher)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
傳送門
?
manacher......
先跑一邊manacher是必須的
然后枚舉雙倍回文串的對稱軸x
把這個雙倍回文串分成4段,w wR w wR
發(fā)現(xiàn),只有當 y <= x + p[x] / 2 && y - p[y] <= x 時,y最大才是最優(yōu)解
也就是y在第三段,并且以y為中心的回文串要擴展到x的或左邊,并且y的回文串要被x的包在里面
那么 (y-x) * 4 中最大的就是答案
我們不妨按照 y - p[y] 排序y,枚舉x,依次添加y進入set,從set中找最大的 y <= x + p[x] / 2
?
邊界討論惡心至極
#include <set> #include <cstdio> #include <algorithm> #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) #define N 1100000int n, pos, maxright, ans; int p[N], f[N]; char s[N]; std::set <int> S; std::set <int> :: iterator it;struct node {int id, p; }a[N];inline bool cmp(node x, node y) {return x.p < y.p; }inline void manacher() {int i;s[0] = '$', s[n * 2 + 1] = '#';for(i = n; i >= 1; i--) s[i * 2] = s[i], s[i * 2 - 1] = '#';for(i = 1; i <= n * 2 + 1; i++){p[i] = 1;if(i <= maxright)p[i] = min(p[pos * 2 - i], maxright - i + 1);while(s[i - p[i]] == s[i + p[i]]) p[i]++;if(maxright < i + p[i] - 1){pos = i;maxright = i + p[i] - 1;}}for(i = 1; i <= n; i++) f[i] = (p[i * 2 - 1] - 1) / 2; }int main() {int i, j;scanf("%d", &n);scanf("%s", s + 1);manacher();for(i = 1; i <= n; i++) a[i].id = i, a[i].p = i - f[i];std::sort(a + 1, a + n + 1, cmp);j = 1;for(i = 1; i <= n; i++){while(a[j].p <= i && j <= n)S.insert(a[j].id), j++;it = S.upper_bound(i + f[i] / 2);if(it == S.begin()) continue;it--;ans = max(ans, (*it - i) * 4);}printf("%d\n", ans);return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/zhenghaotian/p/7503376.html
總結
以上是生活随笔為你收集整理的[BZOJ2342] [Shoi2011]双倍回文(manacher)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅析SQL Server在可序列化隔离级
- 下一篇: jdbcType