@@ -4,19 +4,19 @@ http://leetcode.com/2011/11/longest-palindromic-substring-part-i.html
44
55> 给定一个字符串S,找出S中最长的回文子字符串。
66
7- 这道有趣的题目已经成为著名的Greplin http://baike.baidu.com/view/5302414.htm?fr=iciba 编程挑战的专题,而且多次在面试中被问起。为什么?因为该题有多少解法。我知道的解法就有5种。你准备接受挑战吗?
7+ 这道有趣的题目已经成为著名的[ Greplin] ( http://baike.baidu.com/view/5302414.htm?fr=iciba ) 编程挑战的专题,而且多次在面试中被问起。为什么?因为该题有多种解法。我知道的解法就有5种。你准备接受挑战吗?
8+
9+ 到[ 在线评测] ( http://www.leetcode.com/onlinejudge ) 去解决这个问题(你可以提交C++或Java代码来解决)
810
911## 提示
10- 首先,确保你明白回文的意思。回文是一个字符串,正着读反着读都一样。比如,aba是一个回文,abc就不是 。
12+ 首先,确保你明白回文的意思。回文是一个字符串,正着读反着读都一样。比如,"aba"是一个回文,"abc"就不是 。
1113
1214## 通病
13- 试图想出快速解法的 ,都不幸的答错了(但是很容易被纠正 ):
15+ 许多人倾向于找出一个快速解决方案 ,都不幸的答错了(但是很容易纠正 ):
1416
15- ```
16- 反转S变成S’。找出S和S’最长的公共子字符串 http://en.wikipedia.org/wiki/Longest_common_substring 就是最长回文子字符串。
17- ```
17+ > 反转S变成S’。找出S和S’[ 最长的公共子字符串] ( http://en.wikipedia.org/wiki/Longest_common_substring ) 就是最长回文子字符串。
1818
19- 看上去可以工作,让我们看下面的例子 。
19+ 看上去可以工作,让我们看下面的一些例子 。
2020
2121例如,
2222S = “caba” S’ = “abac”
@@ -26,22 +26,22 @@ S和S’最长的公共子字符串是“aba”。
2626S = “abacdfgdcaba” S’ = “abacdgfdcaba”
2727S和S’最长的公共子字符串是“abacd”。很明显这不是一个回文。
2828
29- 我们发现只要在S中存在一个反转的非回文子字符串 ,最长公共子字符串的解法就失败了。修正该解法 ,每次我们找到一个最长公共子字符串,我们检查一下该子字符串和反转子字符串之前的原始字符串是否一样。如果一样,我们更新当前找到的最长公共子字符串;如果不一样,我们跳过它寻找下一个。
29+ 我们发现只要在S中存在一个反转的非回文子字符串的反转的子串 ,最长公共子字符串的解法就失败了。为了修正该解法 ,每次我们找到一个最长公共子字符串,我们检查一下该子字符串和反转子字符串之前的原始字符串是否一样。如果一样,我们更新当前找到的最长公共子字符串;如果不一样,我们跳过它寻找下一个。
3030
31- 该解法时间复杂度是O (N2)使用O(N2)空间(可以改进只使用O(N)空间)。请阅读最长公共子字符串 http://en.wikipedia.org/wiki/Longest_common_substring
31+ 该解法给出了一个时间复杂度是O (N2)的动态规划解法, 使用O(N2)空间(可以改进只使用O(N)空间)。请阅读 [ 最长公共子字符串 ] ( http://en.wikipedia.org/wiki/Longest_common_substring ) 。
3232
3333## 暴力解法,时间复杂度O(N3)
3434暴力解法就是穷举所有可能的子字符串的起止位置,然后挨个检查是否是回文。总共C(N, 2)子字符串(单个字符除外,它不算回文)。
3535
36- 挨个检查每个子字符串的时间复杂度是O(N),运行时复杂度是O (N3)。
36+ 挨个检查每个子字符串的时间复杂度是O(N),总共时间复杂度是O (N3)。
3737
38- ## 动态编程解法 O(N2)时间复杂度 O(N2)空间复杂度
39- 改进数据处理的暴力解法,首先考虑我们如何省去检查是否是回文的不必要的重复计算 。考虑“ababa”。如果我们已经知道“bab”是回文,很明显“ababa”肯定是回文,因为左右两端的字母是一样的。
38+ ## 动态规划解法 O(N2)时间复杂度 O(N2)空间复杂度
39+ 通过动态规划方法来改进暴力解法,首先考虑我们如何避免检查是否是回文的不必要的重复计算 。考虑“ababa”。如果我们已经知道“bab”是回文,很明显“ababa”肯定是回文,因为左右两端的字母是一样的。
4040
41- 公式化如下所示 :
41+ 更严谨的陈述如下所示 :
4242
4343```
44- 定义P[ i, j ] ← true 如果子字符串Si … Sj是回文,否则false.
44+ 定义P[ i, j ] ← true 当且仅当子字符串Si … Sj是回文,否则false.
4545```
4646
4747所以,
@@ -50,14 +50,14 @@ S和S’最长的公共子字符串是“abacd”。很明显这不是一个回
5050P[ i, j ] ← ( P[ i+1, j-1 ] && Si = Sj )
5151```
5252
53- 基本如下 :
53+ 边界条件如下 :
5454
5555```
5656P[ i, i ] ← true
5757P[ i, i+1 ] ← ( Si = Si+1 )
5858```
5959
60- 这就产生了一个直接的数据处理解法 ,我们首先初始化一个和两个字母的回文,然后找出所有三个字母的回文,N个...
60+ 这就产生了一个直观的动态规划解法 ,我们首先初始化一个和两个字母的回文,然后找出所有三个字母的回文,N个...
6161
6262时间复杂度O(N2),空间复杂度O(N2)
6363
@@ -67,7 +67,7 @@ string longestPalindromeDP(string s) {
6767 int longestBegin = 0;
6868 int maxLen = 1;
6969 bool table[1000][1000] = {false};
70- for (int i = 0; i < n; i++)
70+ for (int i = 0; i < n; i++)
7171 table[i][i] = true;
7272 for (int i = 0; i < n-1; i++) {
7373 if (s[i] == s[i+1]) {
@@ -112,7 +112,7 @@ string expandAroundCenter(string s, int c1, int c2) {
112112 }
113113 return s.substr(l+1, r-l-1);
114114}
115-
115+
116116string longestPalindromeSimple(string s) {
117117 int n = s.length();
118118 if (n == 0) return "";
@@ -121,7 +121,7 @@ string longestPalindromeSimple(string s) {
121121 string p1 = expandAroundCenter(s, i, i);
122122 if (p1.length() > longest.length())
123123 longest = p1;
124-
124+
125125 string p2 = expandAroundCenter(s, i, i+1);
126126 if (p2.length() > longest.length())
127127 longest = p2;
@@ -131,4 +131,4 @@ string longestPalindromeSimple(string s) {
131131```
132132
133133## 进一步思考
134- 是否存在O(N)的解法?你打赌!但是,它需要非常聪明的洞察力。第二部 https://github.com/xiangzhai/leetcode/blob/master/question/longest-palindromic-substring-part-ii.md 将讲解O(N)的解法。
134+ 是否存在O(N)的解法?你打赌!但是,它需要非常聪明的洞察力。[ 第二部] ( https://github.com/xiangzhai/leetcode/blob/master/question/longest-palindromic-substring-part-ii.md ) 将讲解O(N)的解法。
0 commit comments