首页 > 代码库 > 【leetcode】Longest Palindromic Substring

【leetcode】Longest Palindromic Substring

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.


动态规划题。时间和空间复杂度都是O(x2),有空再优化一番空间复杂度吧。

类似于最长递增子序列的思想,大循环n次,找长度分别为2,3,...,n的串中最长的回文子序列。比如当前i=3,那么对于s="cabad",我就要找串"cab","aba","bad"中的最长回文字符串。

设置一个表dp[1005][1005],其中dp[i][j]表示s[i,...,j]中最长回文字符串长度。整个算法就可以看作是在填这张表(其实个人感觉动态规划很多问题最后都是填表),而且每次是填一条对角线的。那么如果:

1.s[i] == s[j],那么就看看s[i+1,j-1]是不是一个回文串,如果是,dp[i][j] = dp[i+1][j-1]+2;

2.s[i] != s[j],或者s[i+1,j-1]是不是一个回文串,那么dp[i][j] = max(dp[i+1][j],dp[i,j-1]);

比如s="ccabacd",当考虑dp[1][5],即串cabac时,先看s[2,4]是不是回文串,发现时,所以dp[1][5] = dp[2][4]+2=3+2=5;当考虑dp[1][4]的时候,即串"caba"s[1]!=s[4],那么dp[1,4]=max(dp[2,4],dp[1,3])=3;

代码如下:

 1 class Solution {
 2 public:
 3     string longestPalindrome(string s) {
 4         int dp[1005][1005];
 5         int n = s.size();
 6         int begin = 0;
 7         int maxLen = 1;
 8         
 9         for(int i = 0;i < n;i ++)
10             dp[i][i] = 1;
11 
12         for(int i = 1;i <= n;i++){
13             //计算长度为i的串的最长回文序列长度
14             for(int j = 0;j < n-i;j++){
15                 if(s[j] == s[j+i] && dp[j+1][j+i-1] == i-1){
16                     dp[j][j+i] = i+1;
17                     begin = j;
18                     maxLen = i+1;
19                 }
20                 else{
21                         dp[j][j+i] = dp[j+1][j+i] > dp[j][j+i-1]?dp[j+1][j+i]:dp[j][j+i-1];
22                 }
23             }
24         }
25 
26         return s.substr(begin,maxLen);
27     }
28 };

上述代码实现时因为是每次填写一条对角线,所以和平常循环二维数组的代码略不同。i表示当前遍历到第几条对角线,j则是行号,那么j+i就是对角线上的第j个元素了。

提交的时候超时了一次,因为其实对角线是会越来越短的(分别是n-1,n-2,...,1),j每次循环只要到n-i行就可以了,因为下面的元素一定是被填好的了(如下图所示)。