Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
1
2
3
4
5
6
7 > Input: "babad"
>
> Output: "bab"
>
> Note: "aba" is also a valid answer.
>
>Example:
1
2
3
4 > Input: "cbbd"
>
> Output: "bb"
>
题意很简单:找最长回文串
一开始想到的想法就是把s反转为s’,然后找s和s’的最长共同子串。所以问题又转化成了经典的LCS(LongestCommonString)。
最长公共子串LCS
用动态规划来解决LCS问题相对比较简单。时间复杂度是O(n^2),空间复杂度也是O(n^2)。思路如下:
- 令dp(i,j)来表示以s1[i],s2[j]结尾时两个串目前最长的共同字串。
- 当i,j都非第一个字符时,考虑此时s1[i]==s2[j]是否成立
- 若成立,则dp(i,j) = dp(i-1,j-1) + 1 (即二维表左上角格子数值加上1)
- 若不成立,则dp(i,j) = 0
- 当i,j有一个为首字符(即 i==0||j==0 )时,依旧考虑s1[i]==s2[j]是否成立
- 若成立,dp(i,j) = 1 (因为前面没有字符了)
- 若不成立,dp(i,j) = 0
- 用longest来维护整个过程的最大值
具体实现如下:
1 | // |
以上代码过了样例,但是交上去却发现WA了。
对比LeetCode给出的出错的输入数据,发现上面的想法是有瑕疵的。例如下面的例子:
- s1=”abcdfcba”
这样子反转后为:
- s2=”abcfdcba”
s1和s2的最长公共子串为abc,但是abc并不是回文串,那么问题出在哪儿了呢?最主要就是在s2找出的共同子串并不在s1对应的位置上。所以,需要对上述想法进行修正加强,在更新最长子串时,要判断这个子串是否在s1对应的位置上,即
1 | s1[i - dp[i][j] + 1] == s2[j] |
完整AC的代码如下:
1 | class Solution { |