標籤:manacher
Longest Palindromic Substring Total Accepted: 17474 Total Submissions: 84472My Submissions
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
先解釋一下題目的意思:
題目要求字串的迴文子字串,所謂的迴文字串就是從左向右讀和從右向左讀都一樣的字串,例如:“abcba”或者“abba”
題目還假設字串的最大長度為1000,而且有且只有一個最大的迴文子字串。
從上面的例子可知,迴文字串有奇偶之分,我們在字串中插入特殊字元,把偶的情況也作為奇的情況處理:
例:abc -> @#a#b#c#$ (頭尾插入不同的特殊字元是為了防止越界)
最簡單的方法:
遍曆字串,使用一個數組prad[ ],prad[ i ]儲存以第 i 個字元為中心的迴文字串的半徑(這個新字串的半徑就剛好等於原字串的長度)
然後再遍曆這個數組就可以輕易得到子迴文字串了:
class Solution {public:string change(string s) {string result = "!";for (int i = 0; i < s.length(); i++) {result += "#";result += s[i];}result += "#?";return result;}string longestPalindrome(string s){if (0 == s.length()){return "";}string new_s = this->change(s);int size = new_s.length();int* prad = new int[size];for (int i = 1; i < size - 1; i++) {prad[i] = 0;while (new_s[i - prad[i] - 1] == new_s[i + prad[i] + 1]){prad[i]++;}}int maxLen{}, start_pos{};for (int i = 1; i < size - 1; i++){if (maxLen < prad[i]){maxLen = prad[i];start_pos = (i - maxLen - 1) / 2;}}delete[]prad;return s.substr(start_pos, maxLen);}};
該演算法的複雜度是O(n2),每一次都重新匹配太浪費時間了,我們可以利用前面匹配得到的資訊,將下次匹配的範圍縮小一點,這就是傳說中的Manacher演算法:
class Solution {public:string change(string s) {string result = "!";for (int i = 0; i < s.length(); i++) {result += "#";result += s[i];}result += "#?";return result;}string longestPalindrome(string s){if (0 == s.length()){return "";}string new_s = this->change(s);int size = new_s.length();int* prad = new int[size];int right_end{}, pos{};//記錄匹配到的迴文字串達到的最右邊,和該字串的中心位置for (int i = 1; i < size - 1; i++) {if (right_end > i){prad[i] = min(right_end - i, prad[2 * pos - i]);}else{prad[i] = 0;}while (new_s[i - prad[i] - 1] == new_s[i + prad[i] + 1]){prad[i]++;}if (i + prad[i] > right_end) {right_end = i + prad[i];pos = i;}}int maxLen{}, start_pos{};for (int i = 1; i < size - 1; i++){if (maxLen < prad[i]){maxLen = prad[i];start_pos = (i - maxLen - 1) / 2;}}delete[]prad;return s.substr(start_pos, maxLen);}};
【Leet Code】Longest Palindromic Substring ——傳說中的Manacher演算法