动态规划的三个要点:最优性定理,状态转移方程,边界条件。
动态规划问题的最大难点在于如何选定状态,确定状态转移方程。
动态规划问题的形式多样,在阶段数目上看,有固定阶段数的,以及非固定阶段数的。后者居多。
1.最长回文子串,给定一个字符串,选出该字符串中最长的回文子串序列,例如:“abab”,答案为aba,或在,者bab。
解法1:若第i个字符到第j个字符构成一条回文串,则第i+1到第j-1个字符同样构成回文串。
这样我们就写出了状态转移方程。
p(i,j)成立,当且仅当p(i+1,j-1)成立且Si==Sj。
代码如下:
class Solution {
public:
string longestPalindrome(string s) {
int k = s.length();
int maxlen = 1;
int start = 0;
vector<vector<int>> dp(k,vector<int>(k));
for (int i = 0;i<k;i++)
dp[i][i]=1;
for(int l = 2;l<=k;l++)
{
for(int i = 0;i<k;i++)
{
int j = i+l-1;
if(j>=k)
break;
if(s[i]!=s[j])
dp[i][j]=0;
else
if(l>3)
dp[i][j]=dp[i+1][j-1];
else
dp[i][j]=1;
if(dp[i][j]==1&&l>maxlen)
{
maxlen=l;
start = i;
}
}
}
return s.substr(start,maxlen);
}
};
解法2:
中心扩展法
class Solution {
pair<int,int> expandAroundCounter(string s,int left,int right)
{
while(left>=0&&right<s.length()&&s[left]==s[right])
{
left--;
right++;
}
return {left+1,right-1};
}
public:
string longestPalindrome(string s) {
int maxlen = 1;
int start = 0;
for(int i = 0;i<s.size();i++)
{
auto[left1,right1]=expandAroundCounter(s,i,i);
auto[left2,right2]=expandAroundCounter(s,i,i+1);
if(right1-left1>maxlen-1)
{
maxlen=right1-left1+1;
start = left1;
}
if(right2-left2>maxlen-1)
{
maxlen=right2-left2+1;
start = left2;
}
}
return s.substr(start,maxlen);
}
};