最小上升子序列1

来源:互联网 发布:微商城源码 编辑:程序博客网 时间:2024/05/01 17:27

假设两个序列分别是B D C A B A和 A B C B D A B 求两者最大的共同子序列的长度。

先说明一下子序列于子串的区别:假如是B D C A B A 这个序列,它的子串必须是连续的,即D C A B 是它的字串,但是B C A B就不是它的字串,而它的子序列是可以不连续的无论是B C A B 还是D C B A都是它的子序列。

咱们可以很容易的看出B C B A是两者最大的子序列,下面看机器应该怎么计算。

1.找到将两个字符串定义成一个字符数组,假设为dp[i][j](表示第一个字符串在第i个字符前且第二个字符串在第j个字符前可构成最长子序列的长度)

2.将二维数组赋值,这里有三种情况:1.当i=0或者j=0时dp[i][j]=0

    2.当第一个字符传中的i对应的元素与第二个字符串相等时,dp[i][j] = dp[i-1][j-1]+1

    3.当以上连个条件都不满足时,dp[i][j] = max(dp[i-1][j] , dp[i][j-1])

以上面的数据为例,我们通过赋值可以得到下面这个二维数组:

使用回溯的方式求出序列:1.从最后一个数据开始往前走,如果i序列对应个元素与j序列对应的元素相等,则区该元素左上角对应的元素。

        2.如果两者不相等,取与该元素相邻的最小元素。

3.利用栈输出满足条件的元素。

代码实现如下:

#include<cstdio>#include<cstring>#include<stack>#include<algorithm>using namespace std;int main(){char str1[20];//定义两个字符串用来储存输入的元素//char str2[20];scanf("%s %s",str1+1,str2+1);str1[0] = str2[0] = '0';//如上面的表当i或者j等于0时,字符也是零// int l1=strlen(str1)-1;//计算两个字符串的长度// int l2=strlen(str2)-1;int dp[20][20]={0};//初始化// for(int i=1; i<=l1;i++)//得出二维数组// {for(int j=1 ;j<=l2 ;j++){if(str1[i]==str2[j])dp[i][j]=dp[i-1][j-1]+1;elsedp[i][j]=max(dp[i-1][j],dp[i][j-1]); }}int pos1 = l1;int pos2 = l2;stack<char> S;while(pos1 > 0 && pos2 > 0){if(str1[pos1] == str2[pos2])//回溯// {S.push(str1[pos1]);pos1--;pos2--;}else if(dp[pos1-1][pos2] > dp[pos1][pos2-1]){pos1--;}elsepos2--;}while(!S.empty())//每输出一个元素,将该元素清除// {printf("%c%c",S.top(),(S.size() == 1)?'\n':' ');S.pop();}return 0;}
练习地址:https://cn.vjudge.net/contest/177074
愿你一生清澈明朗,做你愿做之事,爱你愿爱之人!





原创粉丝点击