最大连续子序列VS最长公共子序列

刷到最大连续子序列时,发现它比学算法时做的最长公共子序列简单多了;

主要是:

用一个变量维护最大连续和 
如果当前这个变量小于0的话,就表示这个变量只会拉低连续和的值了,所以将其变为0 
如果当前这个变量大于0,无论它多小,最大连续和加上它都只会增大而不会减小,所以不用改变这个变量 
如果当前变量是0的话,就要根据题目来更新了

代码如下:

#include <iostream>


using namespace std;


int num[10010];
int n,al,ar,amax;


void fun(){
    int sum=num[0];
    int l,r;
    amax=num[0];
    l=r=al=ar=0;
    for(int i=1;i<n;i++){
        if(sum<0){
            sum=0;
            l=r=i;
        }
        sum+=num[i];
        r=i;
        if(sum>amax){
            amax=sum;
            al=l;
            ar=r;
        }
    }
}
int main()
{
    while(cin>>n&&n){
        for(int i=0;i<n;i++)
            cin>>num[i];
        fun();
        if(amax>=0)
            cout<<amax<<" "<<num[al]<<" "<<num[ar]<<endl;
        else
            cout<<0<<" "<<num[0]<<" "<<num[n-1]<<endl;
    }


    return 0;
}

而最长公共子序列则复杂些:

#include<stdio.h>
#include<string.h>


void lcs_len(char a[],char b[],int m,int n,int c[][100],int bd[][100]);
void print_lcs(int b[][100],char a[],int i,int j);


int main(){
int c[100][100];
int bd[100][100];  //c[i][j]记录序列和的最长公共子序列的长度,bd[][]表示运动轨迹,a[][],b[][]为两个字符串
    char a[100]={"ABCBDAB"};
char b[100]={"BDCABA"};   //最长公共子序列为BCBA
int m,n;


m=strlen(a);
n=strlen(b);


lcs_len(a,b,m,n,c,bd);
print_lcs(bd,a,m,n);


return 0;
}


void lcs_len(char a[],char b[],int m,int n,int c[][100],int bd[][100]){
int i,j;


for(i=0;i<=m;i++)  //当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。
c[i][0]=0;
for(j=1;j<=n;j++)
c[0][j]=0;
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){     
if(a[i-1]==b[j-1]){     //从后向前判断,相等 ,就往对角线走,方向值为0
c[i][j]=c[i-1][j-1]+1;
bd[i][j]=0;

else if(c[i-1][j] >= c[i][j-1]){     //不等,就取长度中的大者,向上,方向值为1,向左,方向值为-1,见书本179面
c[i][j]=c[i-1][j];
bd[i][j]=1;
}
else{
c[i][j]=c[i][j-1];
bd[i][j]=-1;
}
}
}
}


void print_lcs(int bd[][100],char a[],int i,int j){
if(i==0||j==0)
return ;
if(bd[i][j]==0){
print_lcs(bd,a,i-1,j-1);   //从后往前,递归调用进行输出
printf("%c ",a[i-1]);
}
else if(bd[i][j]==1)
print_lcs(bd,a,i-1,j);
else
print_lcs(bd,a,i,j-1);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值