话不多说,先上题!
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
解题思路
采用动态规划算法。
- 状态表示:使用p[i][j]表示字符串中下标i到j的子字符串是否为回文串,若为回文串则p[i][j]=1否则p[i][j]=0。
- 状态转移:通过观察长度大于2回文串可知,当左右边界各去除相同个字符后得到的子串仍为回文串;而当回文串的长度等于2时两字符相同;长度为1的字符串均为回文串。故可得到状态转移方程为:
//当长度>2时,p[i][j] = p[i+1][j-1]&&s[i]==s[j];
//当长度=2时,p[i][j] = (s[i]==s[j]);
//当长度=1时,p[i][j] = 1; - 确定边界:首先确定一个行数和列数均为字符串长度的矩阵。规定初始状态为矩阵各元素均初始化为0,最小子问题为矩阵中各元素表示的子字符串是否为回文串,结束条件为所有元素确定状态完毕。
代码
class Solution {
public:
string longestPalindrome(string s) {
//动态规划算法
//当长度>2时,p[i,j] = p[i+1,j-1]&s[i]==s[j];
//当长度=2时,p[i,j] = (s[i]==s[j]);
//当长度=1时,p[i,j] = 1;
int n = s.length();
if(n < 2) {
return s;
}
string ans;
vector<vector<int>> v(n, vector<int>(n));
for(int l = 0; l < n; ++l) {
for(int i = 0; i+l < n; ++i) {
int j = i + l;
if(l == 0) {
v[i][j] = 1;
} else if(l == 1) {
v[i][j] = (s[i]==s[j]);
} else {
v[i][j] = (v[i+1][j-1] && s[i]==s[j]);
}
if(v[i][j] && l >= ans.size()) {
ans = s.substr(i, l+1);
}
}
}
return ans;
}
};