题目来源
求字符串里最长的回文串。最简单的方法就是暴力直接搜。
代码如下:
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size(), longest = 0;
string res = "";
if (n == 0)
return res;
for (int i=0; i<n; i++)
for (int j=i; j<n; j++)
if (isPalindrome(s, i, j) && isPalindrome(s, i, j) > longest) {
longest = isPalindrome(s, i, j);
res = s.substr(i, j-i+1);
}
return res;
}
int isPalindrome(string s, int start, int end)
{
int i = start, j = end;
while (i <= j) {
if (s[i] != s[j])
return 0;
i++, j--;
}
return end - start + 1;
}
};
代码想法都很简单,但是复杂度高达O(n^3), 这种弱鸡解法的结局只有一个…那就是超时。好吧,再想想。然后想了个O(n^2)的弱鸡解法,就是把i , j
的结果存一下,实际上就是DP。然后解法如下:
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
string res = "";
if (n == 0)
return res;
res = s[0];
int longest = 1;
vector<vector<int>> dp(n, vector<int>(n, 0));
for (int i=0; i<n; i++)
dp[i][i] = 1;
for (int i=1; i<n; i++)
for (int j=0; j<n; j++)
if (j+i<n && ((j+i-1 >= j+1 && dp[j+1][j+i-1] == 1) || i == 1) && s[j] == s[j+i]) {
dp[j][j+i] = 1;
if (i+1 > longest) {
longest = i + 1;
res = s.substr(j, i+1);
}
}
return res;
}
};
可以AC,不过解法真的很烂,应该是有O(n)的方法的吧。
看了下,并没有,不过优化了很多,做法是从头到尾遍历,然后从中间向两边扩展。这样确实快很多。差不多接近O(n)了吧。
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if (n == 0)
return "";
int start = 0, maxLen = 1;
for (int i=0; i<n; ) {
int j = i, k = i;
while (k < n - 1 && s[k+1] == s[k])
k++;
i = k + 1;
while (k < n - 1 && j > 0 && s[k+1] == s[j-1]) {
j--, k++;
}
if (maxLen < k - j + 1) {
start = j;
maxLen = k - j + 1;
}
}
return s.substr(start, maxLen);
}
};