开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
力扣题目: 最长回文子串
题目描述:
这题为动态规划(主要是找到状态转移方程)的子序列问题
解题思路:
先设置数组dp[i][j]表示字符串的闭区间[i,j]内是否为回文字符串, 求解时i,j的顺序
如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的。所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的。当从下到上,从左到右遍历字符串时,如果s[i]==s[j]的时候会有三种情况,
情况1:i==j;dp[i][j]为回文字符串,则dp[i][j]=1;
情况2:j-i==1;dp[i][j]为回文字符串,则dp[i][j]=1;
情况3:当下标i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为回文字符串。
接着如果dp[i][j]==1,那么字符串的闭区间[i,j]内为回文字符串,判断这个回文字符串的长度是否比max大,如果长度比max大,那么就用max,left,right来记录最大的长度,这个回文字符串开始下标,这个回文字符串结束下标,最后利用max,left和right把这个回文字符串提取出来。
提交代码:
int i,j,left=0,right=0,dp[1001][1001]={0},max=0,k=0;
char *p=malloc(sizeof(char)*1001);
int len=strlen(s);
for(i=len-1;i>=0;i--)
{
for(j=i;j<len;j++)
{
if(s[i]==s[j])
{
if(j==i)
dp[i][j]=1;
if(j-i==1)
dp[i][j]=1;
if(j-i>1)
{
if(dp[i+1][j-1]==1)
{
dp[i][j]=1;
}
}
}
if(dp[i][j]==1)
{
if(j-i+1>max)
{
max=j-i+1;
left=i;
right=j;
}
}
}
}
for(i=left;i<=right;i++)
{
p[k++]=s[i];
}
p[k]='\0';
return p;
}