给定一个字符串 s,找到 s 中最长的回文子串。你能够假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
复制代码
首先确认一下什么是回文串,aba
属于回文串,aa
也属于回文串。也就是说回文串分为两种状况,长度为奇数是是以最中间的单个字符开始往两边扩散。长度为偶数时须要以最中间的两个字符开始扩散。所以须要考虑两种扩散方式。web
代码以下:数组
// 从l向左扩散和从r向右扩散,返回此时的最长回文串
string palindrome(string s, int l, int r) {
while(l >= 0 && r < s.size() && s[l] == s[r]) {
l--;
r++;
}
return s.substr(l+1, r-l-1);
}
string longestPalindrome(string s) {
if(s.size() == 0) {
return "";
}
string ans = s.substr(0, 1);
for(int i = 0; i < s.size()-1; i++) {
// 求出从i为中心开始向左右两侧扩散的最长回文串
string same = palindrome(s, i, i);
// 求出从i和i+1为中心开始向左右两侧扩散的最长回文串
string notSame = palindrome(s, i, i+1);
ans = ans.size() < same.size() ? same : ans;
ans = ans.size() < notSame.size() ? notSame : ans;
}
return ans;
}
复制代码
时间复杂度为o(n*n),空间复杂度为o(1)markdown
数组dp[i][j]
表示字符串s
中[i,j]
区间的子串是否为回文串。 咱们能够肯定的是:url
1. if(i == j) dp[i][j] = true
2. if(i < j) dp[i][j] = false
复制代码
如何根据dp[i][j]
来求解其余的值呢?spa
若是s[i]!=s[j],很显然dp[i][j]=false3d
s[i]==s[j]的状况下,若是dp[i+1][j-1]=true,此时dp[i][j]=true,此时咱们能够得出状态转移方程:code
dp[i][j] = dp[i+1][j-1] && s[i]==s[j]
复制代码
根据上图来看,此时咱们已经能够肯定dp[i][j]的值了,由于先决条件已经都有了。可是咱们还须要考虑到一点,在dp[i][i+1]的状况时,即j-i+1=2时,咱们只须要判断s[i]和s[j]是否相等,例如求解dp[0][1]的时候,dp[1][0]=false,已经失去了参考价值。 代码以下:orm
string longestPalindrome(string s) {
size_t length = s.size();
int dp[length][length];
int maxLen = 1;
int start = 0;
for(int i = 0; i < length; i++) {
dp[i][i] = true;
}
for(int j = 1; j < length; j++) {
for(int i = 0; i < j; i++) {
if(s[i] != s[j]) {
dp[i][j] = false;
}else {
if(j - i < 2) {
dp[i][j] = true;
}else {
dp[i][j] = dp[i+1][j-1];
}
if(dp[i][j] && j-i+1 > maxLen) {
start = i;
maxLen = j-i+1;
}
}
}
}
return s.substr(start, maxLen);
}
复制代码
时间复杂度为o(n* n)
,空间复杂度为o(n*n)
ci