您的位置:首页 > 其它

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

2015-08-10 14:55 253 查看
最长公共子序列(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;
}

附测试结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 最大子段和 lcs