最长回文子串(LeetCode 5

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

动态规划法

算法设计

  1. 构造一个长宽等于字符串长度的二维数组dp[len][len],其中len = str.length();
  2. 若原字符串中从第i个字符(从0开始计)到第j个字符之间的子串是符合题目要求的回文子串,则用dp[i][j]表示其长度,若不是回文子串,则记为0
  3. dp[i][j]应该满足如下递归式:

  4. 最后通过max,left定位子串

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private static String findSubstring(String str) {

if (str == null || str.length() == 0) return str;

int[][] dp = new int[str.length()][str.length()];

int len = dp.length;

// 记录数组最大值
int max = 1;

//记录字符串左边界
int left = 0;

// 对角线上的字符为其本身,赋值为1
for (int i = 0; i < len; i++) {
dp[i][i] = 1;
}

for (int j = 1; j < len; j++) {
for (int i = j - 1; i >= 0; i--) {
if (str.charAt(i) == str.charAt(j)) {
if (j - i == 1) {
dp[i][j] = 2;
} else {
dp[i][j] = (dp[i + 1][j - 1] > 0)? dp[i + 1][j - 1] + 2 : 0;
}
} else {
dp[i][j] = 0;
}
if (dp[i][j] > max) {
max = dp[i][j];
left = i;
}
}
}

return str.substring(left, max + left);
}

前向与后向相等子串

题目描述

设计一个动态规划算法,找到字符串T[1..n]中前向和后向相同的最长连续子串。前向子串和后项子串不能重叠。例如:

  1. 输入“ALGORITHM”,算法返回空串;

  2. 输入“RCURSION”,算法返回“R”;

  3. 输入“REDIVIDE”,算法返回“EDI”。

算法设计

  1. 构造一个长宽等于字符串长度的二维数组dp[len][len],其中len = str.length();

  2. dp[i][j]表示原字符串中从第i个字符(从0开始计)到第j个字符之间符合题目要求的最大长度,由于题目要求不重叠,可将dp[i][i]的值设置为0;

  3. dp[i][j]应该满足如下递归式:

  4. 设置max = 0,left表示包含前向子串和后向子串的最小左边界,比如在“REIE”中,max = 3,left = 1。当str[i]和str[j]相等时,在获得dp[i][j]的值后,令max = dp[i][j],left = i,最终通过这两个参数定位子串

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private static String findSubstring(String str) {

int[][] dp = new int[str.length()][str.length()];

int len = dp.length;

// 记录数组最大值
int max = 0;

//记录字符串左边界
int left = 0;

// 不计算重叠字符,对角线赋值为0
for (int i = 0; i < len; i++) {
dp[i][i] = 0;
}

for (int j = 1; j < len; j++) {
for (int i = j - 1; i >= 0; i--) {
if (str.charAt(i) == str.charAt(j)) {
dp[i][j] = dp[i + 1][j - 1] + 1;
if (dp[i][j] > max) {
max = dp[i][j];
left = i;
}
} else {
dp[i][j] = (dp[i][j - 1] > dp[i + 1][j]) ? dp[i][j - 1] : dp[i + 1][j];
}
}
}

return str.substring(left, max + left);
}