首页 > 其他 > 详细

5. Longest Palindromic Substring【字符串 DP】

时间:2017-04-01 16:20:16      阅读:268      评论:0      收藏:0      [点我收藏+]
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.

版本1:Brute Force    O(n^3)
双指针
——————————————————————————————————
版本2:DP---改进版本1,避免重复计算    O(n^2)   | O(n^2) 

该方法可以用于收集整个字符串的回文状态,作为子问题。
类似于LCS,是LCS与KMP的变种,若采用LCS是有问题的,因为公共子串未必是回文串

解:

状态:定义二维数组P[i,j]用以表示Si…Sj是回文(true)或不是回文(false)

状态转移方程 : P[i,j] = (P[i + 1, j - 1] && Si ==Sj)

初始条件是:P[i, i]=true,P[i, i + 1] = (Si == Si+1)

C++版( 使用 C++ 、java可以A , Python超时

  1. class Solution {
  2. public:
  3. string longestPalindrome(string s) {
  4. int l = s.length();
  5. bool p[1000][1000] = {false};
  6. int max_len = 1 , max_beg = 0;
  7. p[l-1][l-1] = true;
  8. for(int i=0;i<l;i++){
  9. p[i][i] = true;
  10. if(s[i] == s[i+1]){
  11. p[i][i+1] = true;
  12. max_len = 2;
  13. max_beg = i;
  14. }
  15. }
  16. for(int length=3 ;length<=l ;length++){
  17. for(int i=0;i<=l-length;i++){
  18. int j = i+length-1;
  19. if(s[i] == s[j] && p[i+1][j-1]){
  20. p[i][j] = true;
  21. max_beg = i;
  22. max_len = length;
  23. }
  24. }
  25. }
  26. return s.substr(max_beg,max_len);
  27. }
  28. };
Java版
  1. public class Solution {
  2. public String longestPalindrome(String s) {
  3. int n = s.length();
  4. if( n == 0 ) return s;
  5. String str = s.substring(0,1);
  6. boolean[][] dp = new boolean[n][n];
  7. for ( int i=0;i<n-1;i++ ){
  8. dp[i][i] = true;
  9. if( s.charAt(i) == s.charAt(i+1) ){
  10. str = s.substring(i,i+2);
  11. dp[i][i+1] = true;
  12. }
  13. }
  14. dp[n-1][n-1] = true;
  15. //初始化完成 O(n)
  16. for( int i=n-2;i>=0;i-- )
  17. for( int j=i+2;j<n;j++ ){
  18. dp[i][j] = dp[i+1][j-1] && (s.charAt(i) == s.charAt(j));
  19. if( dp[i][j] == true && j-i+1 > str.length() )
  20. str = s.substring(i,j+1);
  21. }
  22. return str;
  23. }
  24. }

Python版
  1. s=‘gsdabcdcbaee‘
  2. l = len(s)
  3. p = [[False]*l for i in range(l)]
  4. # init
  5. max_len , max_beg = 1 , 0
  6. p[l-1][l-1] = True
  7. for i in range(l-1):
  8. p[i][i] = True
  9. if s[i] == s[i+1]:
  10. p[i][i+1] = True
  11. max_len = 2
  12. max_beg = i
  13. for length in range(3,l+1):
  14. for i in range(0,l-length+1):
  15. j = i+length-1
  16. if s[i] == s[j] and p[i+1][j-1]:
  17. p[i][j] = True
  18. max_beg = i
  19. max_len = length
  20. print s[max_beg:max_beg+max_len]
——————————————————————————————————

版本3:中心扩展法    O(n^2) |  O(1)       该方法用Python可A,因为最坏情况才n^2,时间更接近n
Python
  1. def Palindromic( s , i , j ):
  2. l = len(s)
  3. curLen = 0
  4. while i>=0 and j<l and s[i] == s[j]:
  5. i -= 1
  6. j += 1
  7. curLen = (j - 1) - (i + 1) + 1
  8. return curLen
  9. class Solution(object):
  10. def longestPalindrome(self, s):
  11. start = 0
  12. max_len = 1
  13. for i in range(len(s)):
  14. curOdd = Palindromic(s,i,i)
  15. if curOdd > max_len:
  16. max_len = curOdd
  17. start = i - curOdd/2
  18. if i+1<len(s):
  19. curEven = Palindromic(s,i,i+1)
  20. if curEven > max_len:
  21. max_len = curEven
  22. start = i + 1 - curEven/2
  23. return s[start:start+max_len]

——————————————————————————————————
版本4:Manacher线性算法  O(n)       改进版本3,
俗称:马拉车算法
Tip1:插入‘#‘可以一次性解决奇偶回文问题             abcdcba  ------------->   #a#b#c#d#c#b#a#
Tip2:记录状态,避免重复计算(回文发生大量重叠 时“abacabaaa”)
Tip3:避免越界前后设置别的符号作为界限。

状态:P[i]记录以i对应元素为中心的最长回文串的半径(包含自己)。
状态转移:p[i] = mx>i? min( p[ 2*id-i ] , mx - i ) : 1

该方程分为三种情况
1、 mx>i 且 mx-i > p[ j ]   (j=2*id-i) ; --> p[ i ] = p [ j ] = p[ 2*id - i ]
2、mx>i 且 mx-i<=p[ j ] ; ---> p[ i ] >= mx-i 继续匹配。
3、mx<=i 无法利用p数组,继续匹配。

  1. public class Solution {
  2. public String longestPalindrome(String s) {
  3. //预处理
  4. StringBuffer sb = new StringBuffer("^#");
  5. for( int i=0;i<s.length();i++ ){
  6. sb.append(s.substring(i,i+1)+"#");
  7. }
  8. sb.append("$");
  9. String str = sb.toString();
  10. //预处理完毕
  11. int[] p = new int[str.length()];
  12. int mx = 0 , id = 0;
  13. for( int i=1;i<str.length()-1;i++ ){
  14. p[i] = mx>i ? Math.min( p[ 2*id-i ] , mx - i + 1 ) : 1;
  15. while( str.charAt( i+p[i] ) == str.charAt( i-p[i] )) ++p[i];
  16. if( p[i] > p[id] ) {
  17. id = i;
  18. mx = i + p[i] - 1;
  19. }
  20. }
  21. return s.substring( (2 * id - mx - 1) / 2 , (mx-1)/2 );
  22. }
  23. }


——————————————————————————————————
版本5:后缀树    O(nlog(n))

暂空
——————————————————————————————————
什么时候使用动态规划法:
? Optimal substructure    最优子结构
? Overlapping subproblems 重叠子问题
构建解的方法:
Characterize structure of optimal solution   状态
Recursively define value of optimal solution 状态转移
Compute in a bottom-up manner 自顶向上
——————————————————

5. Longest Palindromic Substring【字符串 DP】

原文:http://www.cnblogs.com/flyfatty/p/6656423.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!