标签:
题目要求:
给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串。例如,给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc"。
解答:
这个题目的一个简单的解法就是对字符串中的每一个字符,同时向其两边延展,以找到最长回文子串。这种方法是可以的,但要处理回文子串长度为奇数和偶数的两种情况是比较麻烦的。如下图的几个字符串:
“a”
"aa"
"aaa"
"aaaa"
一个比较好的解决方法就是利用Manacher算法。这个算法的核心思想在于为原字符串的开关结尾以及每两个相邻的字符之间加入一个特殊的字符,例如‘#’,以达到统一处理回文子串长度为奇数和偶数的两种情况的目的。如一个字符串为S = “abaaba”,处理之后就是S‘ = “#a#b#a#a#b#a#”。这样,不管回文子串的长度是奇数还是偶数,我们都可以统一处理,因为通过添加特殊字符,原偶数长度的子串中间多了一个特殊字符,这样就能够将其他和奇数长度的字符串一样处理了。我们只需在最后将特殊字符去掉即可。详细可参考LeetCode上的一篇文章。
在LeetCode上通过的C++代码如下:
1 class Solution { 2 public: 3 /** 4 * @param s input string 5 * @return the longest palindromic substring 6 */ 7 string longestPalindrome(string& s) { 8 int sz = s.size(); 9 string newStr; 10 for(int i = 0; i < sz; i++) 11 { 12 newStr += "#" + s.substr(i, 1); 13 } 14 newStr += "#"; 15 16 int szOfNewStr = newStr.size(); 17 int center = 0; 18 int len = 0; 19 20 for(int i = 0; i < szOfNewStr; i++) 21 { 22 int step = 1; 23 int k = i; 24 int tmpCenter = i; 25 int tmpHalfLen = 0; 26 int tmpLen = 0; 27 28 if(newStr[i] == ‘#‘) 29 { 30 while(k - step > -1 && k + step < szOfNewStr && newStr[k - step] == newStr[k + step]) 31 { 32 tmpHalfLen++; 33 step += 2; 34 } 35 tmpLen = 2 * tmpHalfLen; 36 } 37 else 38 { 39 step++; 40 while(k - step > -1 && k + step < szOfNewStr && newStr[k - step] == newStr[k + step]) 41 { 42 tmpHalfLen++; 43 step += 2; 44 } 45 tmpLen = 2 * tmpHalfLen + 1; 46 } 47 48 if(tmpLen > len) 49 { 50 len = tmpLen; 51 center = tmpCenter; 52 } 53 54 } 55 56 string retStr; 57 if(newStr[center] == ‘#‘) 58 { 59 int i = 1; 60 while(i < len) 61 { 62 retStr.insert(retStr.begin(), newStr[center - i]); 63 retStr.insert(retStr.end(), newStr[center + i]); 64 i += 2; 65 } 66 } 67 else 68 { 69 retStr += newStr[center]; 70 int i = 2; 71 while(i < len) 72 { 73 retStr.insert(retStr.begin(), newStr[center - i]); 74 retStr.insert(retStr.end(), newStr[center + i]); 75 i += 2; 76 } 77 } 78 79 return retStr; 80 81 } 82 };
另外,代码已托管至Github.
标签:
原文地址:http://www.cnblogs.com/xiehongfeng100/p/4524134.html