2025年--Lc192-5. 最长回文子串(动态规划在字符串的应用)--Java版
1.题目
2.思路
(1)dp[l][r]:从i到j这段字符串是不是为回文
(2)遍历顺序,right指针从1开始,left指针从0开始,
dp[left + 1][right - 1]表示 去掉首尾字符后 的那段子串是否是回文。
(3)我们现在在判断子串 s[left … right] 是否是回文。
s.charAt(left):左边字符
s.charAt(right):右边字符
左右两边相等:s[left] == s[right]
中间部分 s[left+1 … right-1] 也是回文
那整个字符串 s[left … right] 也一定是回文。
s = "ababa"
假设我们现在想判断 s[0…4] = “ababa” 是否是回文。
首尾字符 s[0] = ‘a’,s[4] = ‘a’ ✅ 相等
那我们就看中间部分 “bab”(也就是 s[1…3])是不是回文。
dp[1][3]:表示的就是 “bab” 是否为回文。
dp[1][3] == true ✅(即 “bab” 是回文)→ 所以 dp[0][4] = true ✅
maxLen = right - left + 1; // = 5
maxStart = left; // = 0
maxEnd = right; // = 4
(4)遍历顺序
right指针要从1开始,从 长度 ≥ 2 的子串 开始检查。
如果right指针从0开始,那么那子串就只有一个字符,比如 “a”,一个字符一定是回文,所以在初始化阶段会被设置成true
left 从 0 开始,要检查所有从 0 到 right 之间的子串,
left 要从 0 一直遍历到 right - 1,覆盖所有可能的起点。
因为我们只关心 起点 < 终点 的子串。
当 left == right 时,子串只有一个字符(已经在初始化阶段处理了)。
当 left > right 时,就不构成合法的子串了。
(right - left <= 2) 表示子串的长度 ≤ 3 时,不需要看 dp[left + 1][right - 1]。
dp[left + 1][right - 1]可能初始化就是false ,就不会等于true了
例子
3.代码实现
class Solution {public String longestPalindrome(String s) {//空字符串或单个字符串if(s.length()==0||s.length()==1){return s;}//字符串的长度int n=s.length();//定义dp[i][j]数组:表示从i到j这段字符串是否为回文boolean[][] dp=new boolean[n][n];//定义最长回文串的起始索引int maxBegin=0;//定义最长回文串的结束索引int maxEnd=0;//定义最大回文串的长度,单个字符也是回文串int maxLen=1;//遍历顺序,right指针,left指针for(int right=1;right<n;right++){for(int left=0;left<right;left++){if(s.charAt(left)==s.charAt(right)&&(right-left<=2||dp[left+1][right-1]==true)){dp[left][right]=true;// 只在更长时更新if(right-left+1>maxLen){//如果此时的长度大于初始化的长度maxLen=right-left+1;maxBegin=left;maxEnd=right;}}}}return s.substring(maxBegin,maxEnd+1);}
}