问题描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
问题分析
对于字符串数组s,用dp[i][j]判断从s[i]到s[j]是否是回文串,如果是,dp[i][j]为1,如果不是回文串,dp[i][j]为0。
则有动态方程dp[i][j]=dp[i+1][j-1]&&(s[i]==s[j]) ,j>=i+2
例如,如果"aba"是回文串,那么"xabax"也是会回文串。
特别的,当j ==i时,也视为回文串,即dp[i][i]=1,例如单个字母a。
当j ==i+1时,即dp[i][i+1]=(s[i]==s[j])
实质上这就是一个完善二维表的过程,二维表的长和宽是字符串的长度,主对角线全部为1,然后以主对角线斜向上逐步完善上三角,在完善过程中,找到满足条件的最大回文子串,当上三角完成后,即可输出结果。
代码实现
假如代码实现多组输入,先输入一个m,决定输入字符串的个数。
#include <bits/stdc++.h>
using namespace std;
const int MAX=1010;
int dp[MAX][MAX];
int main()
{
int m;
string s,ans;
cin>>m;
while(m--)
{
cin>>s;
ans="";
int n=s.size();
for(int k=0;k<n;k++) //这是要循环n次,实现从主对角斜向上完善上三角矩阵。
for(int i=0;i+k<n;i++){
//i和k的下标都从0开始是最好的,见下面解析
int j=i+k;
if(k==0) dp[i][i]=1;
else if(k==1) dp[i][j]=s[i]==s[j];
else dp[i][j]=dp[i+1][j-1]&&s[i]==s[j];
if(dp[i][j]&&k+1>ans.size()){
ans=s.substr(i,k+1);
}
}
cout<<ans<<endl;
}
return 0;
}
问题总结
1.string字符串赋空值,好像不能像java一样,直接s=null,需要这样 s="",让字符串等于空字符串。
2.string字符串的取子串substr函数,str.substr(pos,len),返回从pos开始的长度为len的string字符串。
3.i 的下标不能从1开始,本来打算i从1到n,即dp表的第0行不要,完成从第一行到第n行的上三角,但是发现了错误,那样的话动态方程也要改变了,变成dp[i][j]=dp[i+1][j-1]&&(s[i-1]==s[j-1]),细品,dp数组时从1开始的,而字符串数组s是从0开始的。
4.同理,k的下标应该也从0开始,例如,当k=0时,对应的刚好是主对角线,当k等于1时,对应的是主对角线上移的对角线。