Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad" Output: "bab" Note: "aba" is also a valid answer.
Example:
Input: "cbbd" Output: "bb"
这也是《算法导论》中的一个练习题,先给一个自己想的算法(最坏情况的时间复杂度为O(n2)):
class Solution { public: string longestPalindrome(string s) { if (s.size() == 0) return 0; int i = 0, j = s.size() - 1; int flag = 0; int subscript = j; string s1 = ""; while (i < j) { while (i < j) { if (s[i] == s[j]) { s1 += s[j]; subscript = --j; i++; flag = 1; break; } j--; flag = 0; } if (!flag) { j = subscript; i++; } } int k = 0, l = s.size() - 1; flag = 0; subscript = l; string str = s; reverse(str.begin(), str.end()); string s2 = ""; while (k < l) { while (k < l) { if (str[k] == str[l]) { s2 += str[l]; subscript = --l; k++; flag = 1; break; } l--; flag = 0; } if (!flag) { l = subscript; k++; } } int l1 = s1.size(), l2 = s2.size(); s1 = l2 > l1 ? s2 : s1; if (i >= k && i > j) { string str = s1; reverse(str.begin(), str.end()); s1 += str; } else if (k > i && k > l) { string str = s1; reverse(str.begin(), str.end()); s1 += str; } else { string str = s1; reverse(str.begin(), str.end()); s1 += s[l1 >= l2 ? i : k]; s1 += str; } return s1; } };
两段二重循环的目的是:第一段从右到左缩短str来得到回文子串s1;第二段将原来的字符串反转,然后同样的方式得到一个回文子串s2,然后返回最长的。
但结果Leetcode以这种方式拒绝了:
Input: "abcda" Output: "ada" Expected: "a"
但我不觉得我的错了啊...书上说:character,返回:carac,但在Leetcode竟然错了。。。看来和书上问题并不太一样。
完整代码(可以返回最长回文子串的长度):
#include "stdafx.h" #include <iostream> #include <vector> #include <string> #include <algorithm> class Solution { public: std::string LPS(std::string str) { if (str.size() == 0) return 0; int r1 = 1; int i = 0, j = str.size() - 1; int flag = 0; int subscript = j; std::string s1 = ""; while (i < j) { while (i < j) { if (str[i] == str[j]) { s1 += str[j]; subscript = --j; i++; r1++; flag = 1; break; } j--; flag = 0; } if (!flag) { j = subscript; i++; } } int r2 = 1; int k = 0, l = str.size() - 1; flag = 0; subscript = l; std::string s = str; std::reverse(s.begin(), s.end()); std::string s2 = ""; while (k < l) { while (k < l) { if (s[k] == s[l]) { s2 += s[l]; subscript = --l; k++; r2++; flag = 1; break; } l--; flag = 0; } if (!flag) { l = subscript; k++; } } int l1 = s1.size(), l2 = s2.size(); s1 = l2 > l1 ? s2 : s1; if (i >= k && i > j) { std::string s = s1; std::reverse(s.begin(), s.end()); s1 += s; r1--; } else if (k > i && k > l) { std::string s = s1; std::reverse(s.begin(), s.end()); s1 += s; r2--; } else { std::string s = s1; std::reverse(s.begin(), s.end()); s1 += str[l1 >= l2 ? i : k]; s1 += s; } r1 *= 2; r1 = i > j ? r1 : r1 - 1; r2 *= 2; r2 = k > l ? r2 : r2 - 1; r1 = l1 >= l2 ? r1 : r2; std::cout << r1 << std::endl; return s1; } }; int main() { Solution solve; std::string str = "abcda"; std::cout << str << std::endl; std::cout << solve.LPS(str) << std::endl; getchar(); return 0; }
最开始我想到的办法是通过反转s,得到字符串s‘,然后把问题转化成求LCS,但我发现不符合书上要求。但看样子,Leetcode的问题可以用这个方法解决。dp解法我还不会。。。没得到最优子结构,所以推不出递归式...emmm...但我的这个算法可以解决书上的这个问题,平均情况是很快的:我估计能在O(nlgn)以内,最好情况下为:O(n);但最坏情况下,比如:abcdef这类的就是O(n2)。