首页 > 代码库 > 【Leet Code】Longest Palindromic Substring ——传说中的Manacher算法
【Leet Code】Longest Palindromic Substring ——传说中的Manacher算法
Longest Palindromic Substring
Total Accepted: 17474 Total Submissions: 84472My SubmissionsGiven 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算法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。