hihocoder 1032 最長迴文子串 (Manacher演算法 詳解+模板)
描述
小Hi和小Ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。
這一天,他們遇到了一連串的字串,於是小Hi就向小Ho提出了那個經典的問題:“小Ho,你能不能分別在這些字串中找到它們每一個的最長迴文子串呢?”
小Ho奇怪的問道:“什麼叫做最長迴文子串呢?”
小Hi回答道:“一個字串中連續的一段就是這個字串的子串,而回文串指的是12421這種從前往後讀和從後往前讀一模一樣的字串,所以最長迴文子串的意思就是這個字串中最長的身為迴文串的子串啦~”
小Ho道:“原來如此!那麼我該怎麼得到這些字串呢?我又應該怎麼告訴你我所計算出的最長迴文子串呢?
小Hi笑著說道:“這個很容易啦,你只需要寫一個程式,先從標準輸入讀取一個整數N(N<=30),代表我給你的字串的個數,然後接下來的就是我要給你的那N個字串(字串長度<=10^6)啦。而你要告訴我你的答案的話,只要將你計算出的最長迴文子串的長度按照我給你的順序依次輸出到標準輸出就可以了!你看這就是一個例子。”
提示一提示二提示三提示四3
abababa
aaaabaa
acacdas
樣例輸出
7
5
3
題目連結:http://hihocoder.com/problemset/problem/1032
題目分析:Manacher演算法可以在O(n)的時間複雜度內解決最長迴文子串問題,下面介紹一下這個演算法
首先對於一個任意長度的字串,通過插入無關字元法均可以將其變成奇數長度,如aba => #a#b#a#,abba => #a#b#b#a#,為了解決邊界問題可以直接在最前面再加上一個無關字元,令cur為當前能延伸到最右端的迴文子串的中心位置,p[cur]表示當前能延伸到最右端的迴文子串的迴文半徑,而p[cur] + cur就是當前能延伸到的最右端,當前位置i如果在其範圍之外,即p[cur] + cur < i則p[i] = 1(自己另起一段迴文子串),如果p[cur] + cur >= i,也就是當前位置在其範圍內,則此時p[i] = min(p[cur * 2 - i],p[cur] + cur - i),這裡分兩種情況,1) p[cur * 2 - i] > p[cur] + cur - i,也就是說以i當前的對稱點為中心的迴文子串範圍在當前cur為中心的迴文子串的最左端的左邊,則這時p[i] = p[cur] + cur - i;p[cur] + cur - i指的是當前cur為中心的迴文串的最右端到當前點i的距離,2) p[cur * 2 - i] <= p[cur] + cur - i,情況類似上面,畫圖很容易看出來,算出p[i],則以當前的i為中心向兩端擴充套件,若擴充套件出來的最右端超過原來的最右端則更新cur
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 1e6 + 5;
char s[MAX << 1];
int p[MAX << 1];
int Manacher()
{
int len = strlen(s);
for(int i = len; i >= 0; i--)
{
s[(i << 1) + 2] = s[i];
s[(i << 1) + 1] = '#';
}
s[0] = '*';
int cur = 0, ans = 0;
for(int i = 2; i < 2 * len + 1; i++)
{
if(p[cur] + cur >= i)
p[i] = min(p[(cur << 1) - i], p[cur] + cur - i);
else
p[i] = 1;
while(s[i - p[i]] == s[i + p[i]])
p[i] ++;
if(p[cur] + cur < i + p[i])
cur = i;
ans = max(ans, p[i]);
}
return ans - 1;
}
int main()
{
int n;
scanf("%d", &n);
while(n --)
{
scanf("%s", s);
printf("%d\n", Manacher());
}
}
相關文章
- 最長迴文子串 V2(Manacher演算法)演算法
- LeetCode-5. 最長迴文子串(Manacher)LeetCode
- HDU 3068 最長迴文(Manacher演算法解決最長迴文串問題)演算法
- hdu5371 最長迴文子串變形(Manacher演算法)演算法
- 演算法-兩最長迴文子串演算法
- java 最長迴文子串Java
- 演算法之字串——最長迴文子串演算法字串
- LEECODE 5 求最長迴文子串
- 每天一道演算法題:最長迴文子串演算法
- [動態規劃] 六、最長迴文子串動態規劃
- LeetCode 5.最長迴文子串LeetCode
- Amazon面試題:尋找最長迴文子串面試題
- 今日面試題:最長迴文子串;及迴文分割分析面試題
- leetcode 解題 5. 最長迴文子串 python@ 官解,暴力法,動態法,manacher 法LeetCodePython
- Leetcode[字串] 5. 最長迴文子串LeetCode字串
- 翻譯數字串;及最長迴文子串分析字串
- leedcode-最長迴文串
- 通俗易懂的最長迴文串圖解、說明及Java程式碼(中心擴散法和Manacher演算法)圖解Java演算法
- 程式碼隨想錄演算法訓練營 | 647. 迴文子串,516.最長迴文子序列演算法
- 程式碼隨想錄day46 || 647 迴文子串, 516 最長迴文子序列
- 每日一道 LeetCode (48):最長迴文子串LeetCode
- [LeetCode] Longest Palindromic Substring 最長迴文子串LeetCode
- ural 1297 最長迴文子串 字尾陣列陣列
- 最長子串
- LeetCode - 409 - 最長迴文串LeetCode
- 程式碼隨想錄演算法訓練營day46| 647. 迴文子串 516.最長迴文子序列演算法
- lc1771 由子序列構造的最長迴文串的長度
- Leetcode5: Longest Palindromic Substring(最長迴文子串)LeetCode
- 程式碼隨想錄演算法訓練營第五十七/天 | 516. 最長迴文子序列,647. 迴文子串演算法
- Manacher-求最長迴文字串字串
- 最長迴文子串(百度筆試題和hdu 3068)筆試
- lCS(最長公共子串)
- L2-008 最長對稱子串【最長迴文字串】字串
- Leetcode 344:驗證迴文串(最詳細解決方案!!!)LeetCode
- 找到最長迴文字串 - Manacher's Algorithm字串Go
- Manacher演算法詳解演算法
- 演算法-無重複字元的最長子串演算法字元
- 線性dp:最長公共子串