5.最长回文子串
LeetCode参考:https://leetcode.cn/problems/longest-palindromic-substring/description/
算法设计思路
回文串的性质:对于一个子串而言,如果它是回文串,并且长度大于 2 2 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。例如对于字符串 “ababa”,如果我们已经知道 “bab”是回文串,那么 “ababa”一定是回文串。
原问题的解可以由子问题得到,因此可以使用动态规划解决该问题。
我们用 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示字符串 s s s 以 i i i 开始,以 i i i 结尾的回文串长度:
- 若不是回文串,则 d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0;
- 若是回文串,则 d p [ i ] [ j ] dp[i][j] dp[i][j] 记录回文串的长度。
在填充 d p dp dp 数组的过程中,从斜对角线依次往右上填充:
- 如果 i > j i > j i>j,则根本不是合法的子串,填充为 0 0 0;
- 如果 i = = j i == j i==j,即为斜对角线上的元素,填充为 1 1 1;
- 如果子串长度为
2
2
2,判断
s
[
i
]
=
=
s
[
j
]
s[i]==s[j]
s[i]==s[j]:
- 如果 s [ i ] = = s [ j ] s[i]==s[j] s[i]==s[j],则 d p [ i ] [ j ] = 2 dp[i][j] = 2 dp[i][j]=2;
- 否则,保持为 0 0 0 不变。
- 如果子串长度不小于
3
3
3,判断
s
[
i
]
=
=
s
[
j
]
s[i]==s[j]
s[i]==s[j] 和
s
[
i
+
1
,
j
−
1
]
s[i+1, j-1]
s[i+1,j−1] 是否为回文串:
- 如果 s [ i ] = = s [ j ] s[i]==s[j] s[i]==s[j] 且 s [ i + 1 , j − 1 ] s[i+1, j-1] s[i+1,j−1] 为回文串,则 ;
- 否则,保持为 0 0 0 不变。
在填充过程中设置”锚点“:row
、col
,用于回到每一个斜列开始位置。
在求出 d p dp dp 数组后,遍历 d p dp dp 数组,找到最长回文子串的长度,根据 i i i 和 j j j 构造出解,即最长回文子串。
以 s = s = s= “ b a b a d babad babad” 为例,算法的运行过程如下:
源码
class Solution { public String longestPalindrome(String s) { if (s == "" || s.length() == 0) { return ""; } int n = s.length(); // dp[i][j] 表示字符串索引从 i 到 j 的子串是不是回文串,如果是,填写回文串长度,否则,填充0 int[][] dp = new int[n][n]; // 最长回文子串 String str = null; int i = 0; // 行 int j = 0; // 列 // 锚点,记录每一斜列的开始位置 int row = 0; int col = 0; // 填充dp数组 while (row < n && col < n) { // i == j, 只有一个字符的字符串 while (i == j && i < n && j < n) { dp[i][j] = 1; i++; j++; } // 子串长度为2 while ((j - i + 1) == 2 && i < n && j < n) { if (s.charAt(i) == s.charAt(j)) { dp[i][j] = 2; } i++; j++; } // 子串长度不小于3 while ((j - i + 1) >= 3 && i < n && j < n) { // 如果s[i..j]是回文子串,那么去掉s[i]和s[j]也是回文子串 if (s.charAt(i) == s.charAt(j) && (dp[i + 1][j - 1] != 0)) { dp[i][j] = dp[i + 1][j - 1] + 2; } i++; j++; } i = row; j = col + 1; row = i; col = j; } // 遍历dp数组,找出最长回文子串的长度,构造解 int maxLen = 0; for (int p = 0; p < n; p++) { for (int q = 0; q < n; q++) { if (dp[p][q] == 0 ) continue; if (dp[p][q] > maxLen) { maxLen = dp[p][q]; str = s.substring(p, q + 1); } } } return str; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了