刷到最大连续子序列时,发现它比学算法时做的最长公共子序列简单多了;
主要是:
用一个变量维护最大连续和
如果当前这个变量小于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);
}