LCS 最大子段和,最大子段和在原数组的首末地址

最长公共子序列(lcs)算法是一种非常基础的算法,其主要作用是找出两个序列中的最长公共子序列,但这个算法似乎只找到了两个序列最长公共子序列里边元素的个数,并没有具体的把最长公共子序列求出来,例如s1为123456,s2为124678,他们的最长公共子序列时1246,但lcs似乎只能返回子序列1246里边的元素个数 4 ,并没有返回子序列;

代码为:

#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
char c[500],s[500];
int dp[500][500],i,n,m,j;
int main()
{
	while(scanf("%s%s",c,s)!=EOF)
	{
		int len=strlen(c);
		int lem=strlen(s);
		memset(dp,0,sizeof(dp));//清零dp数组 
		for(i=0;i<len;i++)
		for(j=0;j<lem;j++)
		{
			if(s[j]==c[i])
			{
			dp[i+1][j+1]=dp[i][j]+1;//运用动态规划,假如找到了是s[j]==c[i] ,则值+1; 
			}
			else
			dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);//假如没有找到 ,则在 (dp[i+1][j],dp[i][j+1])里找较大者进行下一轮比较 
		}
		printf("%d\n",dp[len][lem]);
	}
	return 0;
}

最大子段和即为数组里边选取相邻的一段元素,使其和最大,输出最大和,运用了动态规划的思想;下边我贴两个代码,一个是单纯的找到了最大子段和,另一个是找到最大子段和,并找到最大子段和在数组的首尾地址;

查找最大子段和:

#include<stdio.h>
#include<string.h>
int a[1000];
int max(int n)
{
	int sum=0;
	int b=0;
	for(int i=1;i<=n;i++)
	{
		if(b>0)
		b=b+a[i];//当b小于0时,则从下一个记录,当b大于0时继续更新, 
		else
		b=a[i];
		if(b>sum)//储存每一次更新时当前最优解的值,并判断 是否为最终最优解; 
		sum=b;
	}
	return sum;
}
int main()
{
	int i,n;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
		int l=max(n);
		printf("%d\n",l);
	}
	return 0;
}

查找最大子段和,并返回其在数组中的首位地址:

#include<stdio.h>
int a[1010];
void max(int n,int besti,int bestj)//计算最大 子段和 
{
	int sum=0;//最优解 
	int begin=0;
	int b=0;//当前最优解 
	for(int i=1;i<=n;i++)
	{
		if(b>0)
		b=b+a[i];
		else
		{
			b=a[i];
			begin=i;//记录当前最优解开始的地址 
		}
		if(b>sum)
		{
			sum=b;
			besti=begin;
			bestj=i;//i一直在变,begini 可能不变,直到更新了最优解,记录最优解的尾地址. 
		}
	}
	printf("%d 左侧地址是:%d右侧地址是:%d\n",sum,besti,bestj);
}
int main()
{
	int i,n;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
		max(n,0,0);
	}
	return 0;
}

附测试结果:


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值