• [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.

    http://www.acmerblog.com/longest-palindromic-subsequence-5721.html

    最直接的解决方法是:生成给定字符串的所有子序列,并找出最长的回文序列,这个方法的复杂度是指数级的。下面来分析怎么用动态规划解决。

    1)最优子结构

    假设 X[0 ... n-1]  是给定的序列,长度为n.  让 L(0,n-1) 表示 序列 X[0 ... n-1] 的最长回文子序列的长度。

    1. 如果X的最后一个元素和第一个元素是相同的,这时:L(0, n-1) = L(1, n-2) + 2 ,  还以 “BBABCBCAB” 为例,第一个和最后一个相同,因此 L(1,n-2) 就表示蓝色的部分。

    2. 如果不相同:L(0, n-1) = MAX ( L(1, n-1) ,  L(0, n-2) )。 以”BABCBCA” 为例,L(1,n-1)即为去掉第一个元素的子序列,L(0, n-2)为去掉最后一个元素。

    有了上面的公式,可以很容易的写出下面的递归程序:

    #include<stdio.h>
    #include<string.h>
    int lps(char *seq, int i, int j)
    {
       //一个元素即为1
       if (i == j)
         return 1;
       if(i > j) return 0; //因为只计算序列 seq[i ... j]
    
       // 如果首尾相同
       if (seq[i] == seq[j])
          return lps (seq, i+1, j-1) + 2;
    
       // 首尾不同
       return max( lps(seq, i, j-1), lps(seq, i+1, j) );
    }
    
    /* 测试 */
    int main()
    {
        char seq[] = "acmerandacm";
        int n = strlen(seq);
        printf ("The lnegth of the LPS is %d", lps(seq, 0, n-1));
        getchar();
        return 0;
    }

    重叠子问题

    画出上面程序的递归树(部分),已一个长度为6 的字符串为例:

                 L(0, 5)
               /         
              /            
          L(1,5)          L(0,4)
         /                /    
        /                /      
    L(2,5)    L(1,4)  L(1,4)  L(0,3)

    可见有许多重复的计算,例如L(1,4)。该问题符合动态规划的两个主要性质: 重叠子问题 和 最优子结构  

    下面通过动态规划的方法解决,通过自下而上的方式打表,存储子问题的最优解。

    int lpsDp(char * str,int n){
        int dp[n][n], tmp;
        memset(dp,0,sizeof(dp));
        for(int i=0; i<n; i++) dp[i][i] = 1;
        // i 表示 当前长度为 i+1的 子序列
        for(int i=1; i<n; i++){
            tmp = 0;
            //考虑所有连续的长度为i+1的子串. 该串为 str[j, j+i]
            for(int j=0; j+i<n; j++){
                //如果首尾相同
                if(str[j] == str[j+i]){
                    tmp = dp[j+1][j+i-1] + 2;
                }else{
                    tmp = max(dp[j+1][j+i],dp[j][j+i-1]);
                }
                dp[j][j+i] = tmp;
            }
        }
        //返回串 str[0][n-1] 的结果
        return dp[0][n-1];
    }

    方法一:动态规划

    DP, and the state transfer:

    f(i, j) = ture; if i == j
        S[i] == S[j] ,if j = i + 1
        S[i] == S[j] and f(i + 1, j - 1) ,if j > i + 1

    class Solution {
        public:
            string longestPalindrome(string s)
            {
                size_t len = s.size();
                char f[len][len];
                size_t start = 0;
                size_t max = 0;
    
                memset(f,0,sizeof(f));
    
                for(int i = 0; i < len; i++)
                {
                    for(int j = 0; j <= i; j++)
                    {
                        if((j == i) || (i == (j+1) && s[i] == s[j])
                                || ((i > (j + 1)) && s[i] == s[j] && f[j+1][i-1]))
                        {
                            f[j][i] = 1;
                            //cout << "f["<<j<<"][" <<i<<"]
    ";
    
                            if((i - j +1) > max)
                            {
                                start = j;
                                max = i - j + 1;
                            //    cout << "start	" <<start <<endl;
                            //    cout << "max	" <<max<<endl;
                            }
                        }
                    }
                }
                return s.substr(start, max);
            }
    };

    方法二:将原来的字符串reverse一下,为newStr,求原来的str和新的newStr的  longest common substr 即可,对于longest common substr的求法,参考我的下篇随笔。

  • 相关阅读:
    vscode_sync
    外国it视频教学文件
    关于登录状态,后台应该另外做一个接口来决定是否登录
    判断浏览器信息
    file控件预览
    githutb账号密码
    .net core 实践笔记(三)--封装底层
    .net core 实践笔记(二)--EF连接Azure Sql
    .net core 实践笔记(一)--开篇
    SQL引用DAL
  • 原文地址:https://www.cnblogs.com/diegodu/p/4247833.html
Copyright © 2020-2023  润新知