目录
问题 A: 最长公共子序列问题(LCS)之备忘录法
题目描述
使用备忘录法求解两个序列的最长公共子序列的长度。输入
每组输入包括两行,每行包括一个字符串。输出
两个序列的最长公共子序列的长度。
样例输入 Copy
<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">ACBCDABD ABDCABA</span></span></span></span>
样例输出 Copy
<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">5</span></span></span></span>
#include<stdio.h>
#include<string.h>
int max(int a,int b){
return a>=b?a:b;
}
int lsc(char x[],char y[],int i,int j){
if(i==0||j==0) return 0;
if(x[i-1]==y[j-1])
return lsc(x,y,i-1,j-1)+1;
else
return max(lsc(x,y,i,j-1),lsc(x,y,i-1,j));
}
int main(){
char a[100],b[100];
int str1,str2,s=0;
scanf("%s",a);
scanf("%s",b);
str1=strlen(a);
str2=strlen(b);
s=lsc(a,b,str1,str2);
printf("%d\n",s);
}
问题 B: 最长公共子序列问题(LCS)之动态规划法
题目描述
使用动态规划算法求解两个序列的最长公共子序列的长度。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA样例输出 Copy
5
#include<stdio.h>
#include<string.h>
int lsc(char x[],char y[],int m,int n){
int a[100][100];
int i,j;
for(i=0;i<m;i++) a[i][0]=0;
for(j=0;j<n;j++) a[0][j]=0;
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(x[i-1]==y[j-1])
a[i][j]=a[i-1][j-1]+1;
else
a[i][j]=a[i-1][j]>=a[i][j-1]?a[i-1][j]:a[i][j-1];
}
}
return a[m][n];
}
int main(){
char a[100],b[100];
int str1,str2,s=0;
scanf("%s",a);
scanf("%s",b);
str1=strlen(a);
str2=strlen(b);
s=lsc(a,b,str1,str2);
printf("%d\n",s);
}
问题 C: 最长公共子序列问题(LCS)-构造LCS
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
样例输入 Copy
acdbxx ccdxx样例输出 Copy
cdxx
#include<stdio.h>
#include<string.h>
int s[100][100];
void lcslen(char x[],char y[],int m,int n){
int a[100][100];
int i,j;
// 初始化a数组和b数组
for(i=0;i<m;i++) a[i][0]=0;
for(j=0;j<n;j++) a[0][j]=0;
// 动态规划计算LCS长度和路径
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(x[i-1]==y[j-1]){
a[i][j]=a[i-1][j-1]+1;
s[i][j]=1;// 表示当前字符来自x和y的当前位置
}else if(a[i-1][j]>=a[i][j-1]){
a[i][j]=a[i-1][j];
s[i][j]=2; // 表示当前字符来自x的上一位置
}else{
a[i][j]=a[i][j-1];
s[i][j]=3;// 表示当前字符来自y的上一位置
}
}
}
}
void lcs(int i,int j,char x[]){
if(i==0||j==0) return ;
if(s[i][j]==1){
lcs(i-1,j-1,x);
printf("%c",x[i-1]);
}else if(s[i][j]==2) lcs(i-1,j,x);
else lcs(i,j-1,x);
}
int main(){
char a[100],b[100];
int str1,str2;
scanf("%s",a);
scanf("%s",b);
str1=strlen(a);
str2=strlen(b);
lcslen(a,b,str1,str2);
lcs(str1,str2,a);
printf("\n");
}
问题 D: 牛牛的字符串
题目描述
牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。
输入
每组数据包括两行,每行为一个字符串。
输出
输出最长的公共连续子串的长度。
样例输入 Copy
abede abgde样例输出 Copy
2
#include<stdio.h>
int lcs(char x[],char y[],int m,int n){
int dp[100][100];
int i,j;
int a=0;
for(i=0;i<m;i++){
if(x[i]==y[0])
dp[i][0]=1;
}
for(j=1;j<n;j++){
if(x[0]==y[j])
dp[0][j]=1;
}
for(i=1;i<m;i++){
for(j=1;j<n;j++){
if(x[i]==y[j]){
dp[i][j]=dp[i-1][j-1]+1;
a=a>=dp[i][j]?a:dp[i][j];
}
}
}
return a;
}
int main(){
char a[100],b[100];
int str1,str2;
scanf("%s",a);
scanf("%s",b);
str1=strlen(a);
str2=strlen(b);
printf("%d\n",lcs(a,b,str1,str2));
}
问题 E: 最大子段和
题目描述
给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。
输入
每组输入包括两行,第一行为序列长度n,第二行为序列。
输出
输出字段和的最大值。
样例输入 Copy
5 -1 0 1 2 3样例输出 Copy
6
#include<stdio.h>
int solve(int a[],int n){
int b[100]={0};
int max,j;
b[0]=a[0];
max=b[0];
for(j=1;j<n;j++){
if(b[j-1]>0)
b[j]=b[j-1]+a[j];
else
b[j]=a[j];
if(b[j]>max)
max=b[j];
}
return max;
}
int main(){
int n,i;
int a[100];
while(~scanf("%d",&n)){
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
printf("%d\n",solve(a,n));
}
}
问题 F: 最大子段和升级版
题目描述
使用动态规划算法求整数数组(可能包含负整数)的最大子段和,以及和最大子段的起始位置和结束位置:
例如:输入数组(6,-1,5,4,-7),输出14, 1, 4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。输入
每组输入两行,第1行为数组中包含的整数个数n,第2行为n个整数(可能包含负整数),两两之间用空格隔开。
输出
输出最大子段和,以及和最大子段的起始位置和结束位置,两两之间用空格隔开。
样例输入 Copy
5 6 -1 5 4 -7样例输出 Copy
14 1 4
#include <stdio.h>
#include <stdlib.h>
int main (){
int a[100],b[100];
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
b[0]=a[0];
int max=b[0],j=0;
for(int i=1;i<n;i++){
if(b[i-1]>0) b[i]=b[i-1]+a[i];
else b[i]=a[i];
if(max<b[i]){
max=b[i];
j=i;
}
}
int x=j;
while(b[j]>=0&&j>=0)
j--;
printf("%d %d %d\n",max,j+2,x+1);
}
return 0;
}