题目概述
给定两个无空白字符的字符串a,b,求其最长公共子序列的长度
时限
1000ms/2000ms
输入
每行两个字符串a,b,输入到EOF为止
限制
没有限制
输出
每行一个数,最长公共子序列的长度
样例输入
abcfbc abfcab
programming contest
abcd mnp
样例输出
4
2
0
讨论
dp的最长公共子序列,有公式,但额不太理解
意思就是开一个二维数组,将两个字符串各从下标为1的位置摆开,下标0的位置作为基准位置留空,之后对每个位置所在行列对应的字符比较,相同则取左上位置的数+1,否则取左侧和上侧两个位置中较大的值
之所以开二维数组,是求序列的时候方便,但若仅仅求其长度,一维足矣,只要把左上的数单独记录下来即可
题解状态
31MS,1720K,798B,C++
题解代码
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<stack>;
using namespace std;
#define INF 0x3f3f3f3f
#define maxx(a,b) ((a)>(b)?(a):(b))
#define minn(a,b) ((a)<(b)?(a):(b))
#define MAXN 1003
#define memset0(a) memset(a,0,sizeof(a))
char a[MAXN], b[MAXN];
int dp[MAXN];//处理用的二维数组被压缩成一维
int fun()
{
int lena = strlen(a), lenb = strlen(b);//记下字符串长度用于控制循环
for (int p = 1; p <= lena; p++) {
int leftup = 0;//记录每行左上位置的数值 这个位置初始一定是0 因为列下标是0
for (int o = 1; o <= lenb; o++) {//空出0下标位置 从1开始
int up = dp[o];//记录上方的值 因为每个次填入新数后这个位置便被覆盖 所以要提前记录
if (a[p - 1] == b[o - 1])//公式的两种情况
dp[o] = leftup + 1;
else
dp[o] = maxx(dp[o], dp[o - 1]);
leftup = up;//对于下一个数 现在的正上方便是其左上方
}
}
return dp[lenb];
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
while (~scanf("%s%s", a, b)) {//input
printf("%d\n", fun());//output
memset0(dp);
}
}
EOF