Skip to content

Commit 5765dbc

Browse files
committed
feat: update 005
1 parent db178b6 commit 5765dbc

File tree

2 files changed

+55
-22
lines changed

2 files changed

+55
-22
lines changed

note/005/README.md

+29-2
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ class Solution {
6262
## 思路1
6363

6464
如果利用暴力法遍历所有字串是否回文的情况这道题肯定是 `Time Limit Exceeded` 的,那么我们是否可以把之前遍历的结果利用上呢,那么动态规划的想法就呼之欲出了,我们定义 `dp[i][j]` 的意思为字符串区间`[i, j]`是否为回文串,那么我们分三种情况:
65+
6566
1.`i == j` 时,那么毫无疑问 `dp[i][j] = true`
6667
2.`i + 1 == j` 时,那么 `dp[i][j]` 的值取决于 `s[i] == s[j]`
6768
3.`i + 1 < j` 时,那么 `dp[i][j]` 的值取决于 `dp[i + 1][j - 1] && s[i] == s[j]`
68-
根据以上的动态转移方程,我们的问题即可迎刃而解,时间复杂度的话很显而易见,也是 `O(n^2)`
69+
70+
根据以上的动态转移方程,我们的问题即可迎刃而解,时间复杂度的话显而易见,也是 `O(n^2)`
6971

7072
```java
7173
class Solution {
@@ -97,7 +99,32 @@ class Solution {
9799

98100
## 思路2
99101

100-
最后一种思路那就是 `Manacher's Algorithm`,中文名叫马拉车算法,该算法就是专为解决此问题而发明的。
102+
马拉车算法(Manacher's Algorithm)
103+
104+
## 背景
105+
106+
给定一个字符串,求出其最长回文子串。例如:
107+
108+
1. s = "babad",最长回文长度为 `3`,可以是 `bab` 或者 `aba`
109+
2. s = "cbbda",最长回文长度为 `2`,即 `bb`
110+
3. s = "abcde",最长回文长度为 `1`,即单个字符本身。
111+
112+
等同于LeetCode上的第五题:[Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring)
113+
114+
其相关题解可以查看这里:[传送门](https://github.com/Blankj/awesome-java-leetcode/blob/master/note/005/README.md)
115+
116+
以上问题的传统思路大概是,遍历每一个字符,以该字符为中心向两边查找。其时间复杂度为 `O(n2)`,效率很差。
117+
118+
1975 年,一个叫 Manacher 的人发明了一个算法,Manacher 算法(中文名:马拉车算法),该算法可以把时间复杂度提升到 `O(n)`。下面来看看马拉车算法是如何工作的。
119+
120+
最后一种思路那就是 `Manacher's Algorithm`,中文名叫马拉车算法,该算法就是专为解决此问题而发明的,其时间复杂度提升到了线性。下面我以我理解的思路来讲解其原理。
121+
由于回文串的奇偶行不确定,比如 `lol` 是奇回文,而 `lool` 是偶回文,马拉车算法的第一步就是对其进行预处理,做法就是在每个字符两侧都加上一个特殊字符,一般就是不会出现在原串中的即可,我们可以选取 `#`,那么
122+
123+
`lol` -> `#l#o#l#`
124+
`lool` -> `#l#o#o#l#`
125+
126+
这样处理后不管原来字符串长度是奇还是偶,最终得到的长度都将是奇数,这样就能把两种情况合并起来考虑。
127+
101128

102129

103130
## 结语

src/com/blankj/medium/_005/Solution.java

+26-20
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,40 @@ public class Solution {
3333
// st = l + 1;
3434
// end = r - 1;
3535
// }
36+
// }
37+
38+
// public String longestPalindrome(String s) {
39+
// int len = s.length();
40+
// if (len <= 1) return s;
41+
// int st = 0, end = 0;
42+
// char[] chars = s.toCharArray();
43+
// boolean[][] dp = new boolean[len][len];
44+
// for (int i = 0; i < len; i++) {
45+
// dp[i][i] = true;
46+
// for (int j = 0; j < i; j++) {
47+
// if (j + 1 == i) {
48+
// dp[j][i] = chars[j] == chars[i];
49+
// } else {
50+
// dp[j][i] = dp[j + 1][i - 1] && chars[j] == chars[i];
51+
// }
52+
// if (dp[j][i] && i - j > end - st) {
53+
// st = j;
54+
// end = i;
55+
// }
56+
// }
57+
// }
58+
// return s.substring(st, end + 1);
3659
// }
3760

3861
public String longestPalindrome(String s) {
39-
int len = s.length();
40-
if (len <= 1) return s;
41-
int st = 0, end = 0;
42-
char[] chars = s.toCharArray();
43-
boolean[][] dp = new boolean[len][len];
44-
for (int i = 0; i < len; i++) {
45-
dp[i][i] = true;
46-
for (int j = 0; j < i; j++) {
47-
if (j + 1 == i) {
48-
dp[j][i] = chars[j] == chars[i];
49-
} else {
50-
dp[j][i] = dp[j + 1][i - 1] && chars[j] == chars[i];
51-
}
52-
if (dp[j][i] && i - j > end - st) {
53-
st = j;
54-
end = i;
55-
}
56-
}
57-
}
58-
return s.substring(st, end + 1);
62+
63+
return s;
5964
}
6065

6166
public static void main(String[] args) {
6267
Solution solution = new Solution();
6368
System.out.println(solution.longestPalindrome("babad"));
6469
System.out.println(solution.longestPalindrome("cbbd"));
70+
6571
}
6672
}

0 commit comments

Comments
 (0)