【动态规划】【子序列模板】
【最长上升子序列】
输出长度
while(scanf("%s%s",s1+1,s2+1)!=EOF)
{
l1 = strlen(s1+1);
l2 = strlen(s2+1);
for(i = 0; i <= l1;i ++)
f[i][0] = 0;
for(i = 0; i <= l2; i ++)
f[0][i] = 0;
for(i = 1; i <= l1; i ++)
{
for(j = 1; j <= l2; j ++)
{
if(s1[i] == s2[j])//字符相等时,上一个状态长度加1
f[i][j] = f[i-1][j-1] + 1;
else
{//字符不等时,取最大的字符序列公共长度
if(f[i-1][j] > f[i][j-1])
f[i][j] = f[i-1][j];
else
f[i][j] = f[i][j-1];
}
}
}
printf("%d\n",f[l1][l2]);
}
回溯输出最长上升子序列
void LCS(char *x,char *y,int n,int m,int a[][N+10],int b[][N+10] )
{//找到最长公共子序列
for(i = 0; i <= n; i ++)
a[i][0] = 0;
for(j = 0; j <= m; j ++)
a[0][j] = 0;
for( i = 1; i <= n; i ++)
for( j = 1; j <= m; j ++)
{
if(x[i-1] == y[j-1])
{//下标从0开始,故为i-1,j-1。
a[i][j] = a[i-1][j-1]+1;
b[i][j] = 1; //字符相等标记为1
}
else
{
if( a[i-1][j] > a[i][j-1])
{
a[i][j] = a[i-1][j] ;
b[i][j] = 0;//字符串1大标记为0
}
else
{
a[i][j] = a[i][j-1] ;
b[i][j] = -1;//字符串2大标记为1
}
}
}
return;
}
void PrintLcs(char *s,int n,int m,int b[][N+10])
{//回溯输出子序列
if( 0 == n|| 0 == m)
return;
else if( b[n][m] == 1)
{
PrintLcs(s,n-1,m-1,b);
printf("%c",s[n-1]);
}
else if( b[n][m] == 0)
PrintLcs(s,n-1,m,b);
else if(b[n][m] == -1)
PrintLcs(s,n,m-1,b);
}
int main()
{
LCS(str1,str2,l1,l2,a,b);
PrintLcs(str1,l1,l2,b);
printf("\n");
return 0;
}
【最大上升子段和】
/*max_len[N]存1~n各阶段的最大上升子段和*/
max_len[1] = num[1];//数组开始的最大上升子段和是第一个元素
max = num[1];//最大上升子段和初始化
for( i = 1; i <= n; i ++)
{
num_len = 0;//记录i左边的最大上升子段和
for(j = 1; j < i; j ++)//找到i左边的最大上升子段和
{
if(num[i] > num[j])
{
if(num_len < max_len[j])
num_len = max_len[j];
}//if
} //for
max_len[i] = num_len + num[i]; //i左边最大上升子段和加上自身的值
if(max_len[i] > max)
max = max_len[i];
}//for
printf("%d\n",max); //输出最大和
【连续最大子段和之输出最大子段和,起点,终点】
时间复杂度为O(n),舍弃数组存储的方法原因有:1:易粗心错估数据范围,2:降低时间复杂度
#include<stdio.h>
int max_start,max_end;//最终的起始点和最终的终点
int now_start; //当前起始点
int now_sum; //当前的和
int max;//最大子段和
int num; //读入当前值
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF)
{
for(i = 1; i <= n; i ++)
{
scanf("%d",&num);
if( i == 1) //如果是第一个值,初始化数据
{
now_sum = max = num;
now_start = max_end = i;
}
else
{
if( now_sum >= 0)
now_sum += num;
else
{
now_sum = num;
now_start = i; //记录当前起始点
}
}
if( now_sum >= max) //更新最大值
{
max = now_sum;
max_start = now_start; //更新起始点
max_end = i; //更新终止点
}
}
printf("%d %d %d\n",max,max_start,max_end); //输出最大子段和,起始点,终止点
}
return 0;
}