题目描述
给你一个字符串s,找出符合要求的最长子串的长度。
该子串位回文串。
该题没有想出来怎么写?
方法1:中心扩展算法
用改方法是根据的回文串的定义。
回文串:前后相等。回文串有2种:奇数的、偶数的
枚举中心,左右扩展。
细节看具体的代码实现。
时间复杂度:O(N^2)
代码
class Solution {
int start=0,len=1;
public:
string longestPalindrome(string s) {
//枚举回文串的中心
for(int mid=0;mid<s.size();mid++)
{
//左右进行扩展,奇数的回文串
Palindrome(s,mid-1,mid+1);
//偶数的回文串
Palindrome(s,mid-1,mid);
}
return s.substr(start,len);
}
void Palindrome(string& s,int left,int right)
{
//找到不相等的就是边界
while(left>=0&&right<s.size()&&s[left]==s[right]) left--,right++;
if(right-left-1>len) start=left+1,len=right-left-1;
}
};
方法2:动态规划
如果用一维的dp来进行表示:dp[i]
以i结尾的字串为回文串的长度。
那么怎么求dp[i]
。
动态规划都是用已知推未知。必然是用i-1,i-2
等前面的dp值进行操作。
dp[i]要找到于s[i]相等的字符,这个不好找,即使找到,又改怎么做呢?
显然一维是不可以的。
dp[i][j]
表示:以i开始,j结束的字符串是不是回文串。
求dp[i][j]
s[i]==s[j]
:dp[i][j]
=dp[i+1][j-1]
- 不相等,false
因为i,j的结果取决于i+1,j-1。
所以遍历顺序从有往左,从上往下。
代码
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
//初始长度
int start=0,len=1;
for(int i=n-1;i>=0;i--)
{
for(int j=i;j<n;j++)
{
//把初始化放到了这里
if(i==j) dp[i][j]=true;
else if(s[i]==s[j])
{
//这样分类避免i超过j
if(j-i+1==2) dp[i][j]=true;
else dp[i][j]=dp[i+1][j-1];
}
if(dp[i][j]&&j-i+1>len) len=j-i+1,start=i;
}
}
return s.substr(start,len);
}
};