最长回文子串

127 阅读1分钟

题目链接leetcode-cn.com/problems/lo…

给你一个字符串 s,找到 s 中最长的回文子串。

 

示例 1:

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

示例 2:

输入: s = "cbbd"
输出: "bb"

示例 3:

输入: s = "a"
输出: "a"

示例 4:

输入: s = "ac"
输出: "a"

 

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母(大写和/或小写)组成

解法:动态规划。

一:确定状态

根据问题寻找 s 中最长的回文子串。我们假设字符串x为回文串,那么我们在x前后各增加同一个字符,得到的新串肯定为一个回文串。 由此假设可知 (1)最后一步为:在x前后各增加同一个字符,得到最长的回文子串。

(2)子问题:用长为L得回文串str,在其前后各增加同一个字符,得到长为L+2的新回文串

二:确定转移方程 我们用P(i,j) 表示字符串 s 的第 i 到 j个字母组成的串(下文表示成 s[i:j]s[i:j])是否为回文串。

那么P(i,j)我们就可以根据P(i+1,j-1)以及(s[i]==s[j])的情况来判断它是否为回文串,很显然 当P(i+1,j-1)为回文串并且s[i]==s[j]这两个字符相等就符合要求。

如果P(i,j)为true且长度大于已发现得长度,就更新最长的回文子串。(附:j-i+1=L)

三:边界初始化

当j-i<3时,d[i][j]=true。(例如"aba","aa","a")

string longestPalindrome(string s){
    
	
	int len = s.size();
	vector< vector<int> > dp(len, vector<int>(len));	
	int start = 0, maxL = 1;
	for (int L = 1; L <=len; L++)
	{
		for (int i = 0; i < len; i++)
		{
			int j = i + L - 1;
			if (j>=len)
			{
				break;
			}

			if (s[i]!=s[j])
			{
				dp[i][j] = false;
			}
			else
			{
				if (j-i<3)
				{
					
					dp[i][j] = true;
				}
				else
				{
					dp[i][j] = dp[i+1][j-1];
				}
			}

			if (dp[i][j]&&L>maxL)
			{
				start = i;
				maxL = L;
			}

		}
	}
	return s.substr(start, maxL);

}