最长公共子序列和最大字段和+最长不下降序列

【题目描述】
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>,则另一序列Z=<z1,z2,…,zk>Z=<z1,z2,…,zk>是X的子序列是指存在一个严格递增的下标序列<i1,i2,…,ik><i1,i2,…,ik>,使得对于所有j=1,2,…,k有:

Xij=ZjXij=Zj
例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>,则序列<B,C,A>是X和Y的一个公共子序列,序列 <B,C,B,A>也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列.因为X和Y没有长度大于4的公共子序列。

给定两个序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>和Y=<y1,y2….yn>Y=<y1,y2….yn>.要求找出X和Y的一个最长公共子序列。

【输入】
共有两行。每行为一个由大写字母构成的长度不超过1000的字符串,表示序列X和Y。

【输出】
第一行为一个非负整数。表示所求得的最长公共子序列的长度。若不存在公共子序列.则输出文件仅有一行输出一个整数0。

【输入样例】
ABCBDAB
BDCABA
【输出样例】
4【提示】
最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。字符串长度小于等于1000。

【来源】

No

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
int s[1000]; char t[2001];
char p[2001], b[2001];
int dp[2001][2001];
int main() 
{
	
	cin >> b; cin >> p;
	memset(dp, 0, sizeof dp);
	for (int i = 1; i <= strlen(b); i++)
		for (int j = 1; j <= strlen(p); j++)
		{
			if (b[i - 1] == p[j - 1])
				dp[i][j] = dp[i - 1][j - 1] + 1;
			else
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	cout << dp[strlen(b)][strlen(p)] << endl;

}

公共子序列的变形

1、每个队员从出发点开始,沿着一条唯一的笔直道路跑直到终点,途中不允许往回跑,否则将被取消比赛资格。
2、出发前,每个队员的枪膛内都被装了顺序一样的、用小写英文字母标明类型的子弹序列,每位队员被告知这一序列的信息;同时,每位队员也被告知恐怖分子即将出现的序列和类型(同样用小写英文字母标明类型)。
3、在跑动的过程中,若发现“恐怖分子”,特警队员可以选择用枪击毙他,来得到写在“恐怖分子”胸前的得分,但是前提是他使用的子弹类型必须和“恐怖分子”类型相同,否则,即使击毙了“恐怖分子”,也得不到分数;当然选择不击毙他也是可以的,这样他不会从那个“恐怖分子”身上得到分数。
4、允许特警队员放空枪,这样可以消耗掉型号不对的子弹而不至于杀死“恐怖分子”(当然每个特警队员都不会愚蠢到不装消音装置就放空枪,以至于吓跑“恐怖分子”),等待枪口出现正确型号的子弹击毙他得分。
炜炜需要你的帮助,告诉他如何做,才能得到最高的分数。现在如果告诉你出发时枪膛内子弹的序号和型号、恐怖分子出现的序号和类型,你能告诉炜炜他最多能得到多少分数吗?
Input
输入数据的第一行有一个整数N表示子弹和恐怖分子的类型数。随后的一行是各种恐怖分子类型的一行字母,两个字母之间没有任何字符。接下来的一行是击毙上一行对应位置恐怖分子类型的得分数,每个分数之间恰有一个空格。第三第四行分别表示开始时枪膛内子弹的序列(左边的先打出)和恐怖分子出现的序列(左边的先出现),字母之间都没有任何字符。
每个测试数据之间没有空格和空行。你的程序必须通过全部测试数据,才能被判为AC。
Output
对于每一个测试数据,输出炜炜最多能得到的分数。
Sample Input
3
abc
1 1 1
abc
ccc
3
abc
1 1 1
ccc
aba
Sample Output
1
0
变的就是加分数的地方

int n; 
	while (cin >> n)
	{
		for (int i = 0; i < n; i++)
			cin >> t[i];
		for (int i = 0; i < n; i++)
		{
			char h = t[i];
			cin >> s[h];
		}
		cin >> b; cin >> p;
		for (int i = 0; i <= strlen(b); i++)
			dp[i][0] = 0;
		for (int j = 0; j <= strlen(p); j++)
			dp[0][j] = 0;
			用memset  会超时 嘤嘤嘤
	//	memset(dp, 0, sizeof dp);
		for (int i = 1; i <= strlen(b); i++)
			for (int j = 1; j <= strlen(p); j++)
			{
				if (b[i - 1] == p[j - 1])
					dp[i][j] = dp[i - 1][j - 1] + s[b[i - 1]];
				else
					dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
		cout << dp[strlen(b)][strlen(p)]<<endl;
	}

最大字段和。。。。。。。。。。。。。。。。。。。
字段是连续的哦。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
using namespace std;
int  b[100];
int main()
{
	int n; cin >> n;
	int i, c = 0; int maxx = 0;
	for (i = 1; i <=n; i++)
	{
		cin >> b[i];
		if (c > 0)
			c = c + b[i];
		else c = b[i];
		if (maxx < c)
			maxx = c;
	}
	cout<<maxx;
}

③最长不下降序列

以i为尾部 然后再从前往后看。
然后挨个比较,如果 有个数比他小,那第i个数的 序列长度=max(t,l[j]);为两个人的最大值

for( i = 2; i <= N; i ++ ) 
    { 
        int nTmp = 0; //记录第i 个数左边子序列最大长度
        for( j = 1; j < i; j ++ ) 
        { //搜索以第i 个数左边数为终点的最长上升子序列长度
            if( b[i] > b[j] ) 
            {
                if( nTmp < aMaxLen[j] )
                    nTmp = aMaxLen[j];
            }
        }
        aMaxLen[i] = nTmp + 1;
    }
    int nMax = -1;
    for( i = 1;i <= N;i ++ )
        if( nMax < aMaxLen[i])
            nMax = aMaxLen[i];
    printf("%d\n", nMax);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值