算法题 | 动态规划之最长公共子序列(LCS):删除最少字符串使剩下的字符串为回文串

这道题会用到动态规划。题目的描述很简单,见标题。首先让我们明确两个概念: 

最长公共子串(Longest Common Substring),子串是连续的;

最长公共子序列(Longest Common Subsequences), 不一定是连续的。 


思路: 

举个例子,abcdeca这个字符串的逆序为:acedcba. 这两者之间的公共最大子序列为:acdca. 再将其与原字符串相减就是需要删除的最少字符数。这样该问题实际上就是求字符与其反转的最长公共子序列!   

下一步:如何求解两个字符串的最长公共子序列?   当然使用动态规划,用到循环的思路,比起递归时间性能好很多。 

如何构建动态规划的函数关系

首先,第一步确定函数的参数和返回值,也就是函数的自变量和函数值,两个字符串可以想到自变量应该为2个,函数值只涉及到长度就姑且设为最长公共子序列的长度L。 一般来说,动态规划的起步都是从0开始的,也就是说我们可以先假设最简单的情况:如果是str1和str2是两个字符,那么L怎么判断。如果str1一个字符,str2两个字符又怎么判断,这样递推寻找函数关系式。  

我们不妨设函数参数为m, n,分别表示str1和str2字符串的下标位置。  于是,求函数表达式 L(m, n)! 

分析: 1. 如果str1(m) == str2(n), 则 L(m, n) = L(m-1, n-1)       2. 如果str1(m) != str2(n), 则 L(m, n) = max ( L(m, n-1), L(m-1, n) )   

分析好了之后,接下来就是算法实现。在上述的递归函数关系中,肯定要确定好循环的初始条件 

//
// Created by max on 19-4-26.
//

#include <iostream>
#include <cstring>   //memset函数
#include <string>    //string类
#include <cstdio>    //C语言的输入输出
#include <algorithm> //用到max reverse

using namespace std;

const int MAXN = 1005;

int dp[MAXN][MAXN];

int main ()
{

    cin.tie(0);   //解除cin与cout的绑定 加快执行效率
    ios::sync_with_stdio(false);
    //C++中iostream为了兼容C,会用一个流缓冲区同步C的标准流,这一句可以使cin cout不经过缓冲区提高性能

    string s;
    memset(dp, 0, sizeof(dp));

    while( cin >> s )
    {
        string t = s;
        reverse(s.begin(), s.end());

        int len = s.length();
        int maxLen = 0;   //保存最大长度
        for( int i = 0; i < len; ++i)
        {
            if(t[0] == s[i])     //把t字符串下标看做函数L的第一个参数
                while(i < len) dp[0][i++] = 1;
            else
                dp[0][i] = 0;
        } //将动态规划的二维数组中的第一行全部求解了

        for( int i = 0; i < len; i++)
        {
            if( t[i] == s[0])
                while(i < len)  dp[i++][0] = 1;
            else
                dp[i][0] = 0;
        } //第一列

        for(int i=1; i<len; i++)
        {
            for(int j=1; j<len; j++)
            {
                if(t[i] == s[j])
                    dp[i][j] = dp[i-1][j-1] + 1; 
                else 
                    dp[i][j] = max( dp[i-1][j], dp[i][j-1]);    
            }
        }
        
        maxLen = dp[len-1][len-1]; 
        cout << "numbers of char to be deleted:" << len - maxLen << endl;   
        
    }
    
    return 0;    
}

That is all 

Friday 愉快! 

猜你喜欢

转载自blog.csdn.net/weixin_43795395/article/details/89554031
今日推荐