题目描述

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(N²)的算法-动态规划

更简洁的做法,使用动态规划,这样可以把时间复杂度降到O(N²),空间复杂度也为O(N²)。做法如下:

首先,写出动态转移方程。

Define P[ i, j ] ← true iff the substring Si … Sj is a palindrome, otherwise false.

P[ i, j ] ← ( P[ i+1, j-1 ] and Si = Sj ) ,显然,如果一个子串是回文串,并且如果从它的左右两侧分别向外扩展的一位也相等,那么这个子串就可以从左右两侧分别向外扩展一位。

其中的base case是

P[ i, i ] ← true
P[ i, i+1 ] ← ( Si = Si+1 )

然后,看一个例子。

假设有个字符串是adade,现在要找到其中的最长回文子串。使用上面的动态转移方程,有如下的过程:

Longest Palindromic Substring

按照红箭头->黄箭头->蓝箭头->绿箭头->橙箭头的顺序依次填入矩阵,通过这个矩阵记录从i到j是否是一个回文串。

实现代码:

             class Solution {
public:
    string longestPalindrome(string s) {
           int n = s.length();  
           int longestBegin = 0;  
           int maxLen = 1;  
           bool table[1000][1000] = {false};  //建立一个二维数组
           for (int i = 0; i < n; i++) //
           {  
             table[i][i] = true;  //将对角线设为true;自己和自己比较
           }  
           for (int i = 0; i < n-1; i++)
           {  
             if (s[i] == s[i+1]) //两两比较;
             {  
               table[i][i+1] = true;  //前后相等设为true;
               longestBegin = i;  
               maxLen = 2;  
             }  
           }  
           for (int len = 3; len <= n; len++) //依次取长度为3.4.5...直到n
           {  
             for (int i = 0; i < n-len+1; i++)
             {
               int j = i+len-1; //i从0遍历到n-len;j从len-1遍历到n-1;间隔为len
               if (s[i] == s[j] && table[i+1][j-1])//i为头,j为尾;
               {  
                 table[i][j] = true;  
                 longestBegin = i;  //记录开始位置;
                 maxLen = len;  
               }  
             }  
           }  
           return s.substr(longestBegin, maxLen);  
   }
};

解析链接


相关文章: