最长公共子序列
分析:
由于空间限制,肯定不能开5001*5001的数组,仔细分析一下,好像要使用的数据只有两行,故为 f[2][5001]。
求出最长公共上升子序列的长度肯定没问题,
先解释一下状态转移公式的意思:f[i][j]表示Xi与Yj之间的最长子序列长度。
来推一下递推公式(高手总结的传送门):
当a[i] == b[j]时,子序列长度+1,f[i][j] = f[i-1][j-1] + 1;
当a[i] != b[j]时,最长子序列长度为 X(i-1) 与 Y(j-1) 之间 和 Xi 与 Y(j-1)之间 最大值。第二问
输出方案数
先上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define k 100000000
using namespace std;
int f[2][5001],r[2][5001];
char a[5001],b[5001];
int main() {
gets(a);
gets(b);
int la = strlen(a) - 1,lb = strlen(b) - 1;
for(int j = 0; j<=lb; j++) {
r[0][j] = 1;
}
r[1][0] = 1;
for(int i = 1; i<=la; i++) {
for(int j = 1; j<=lb; j++) {
if(i % 2) {
if(a[i-1] == b[j-1]) {
f[1][j] = f[0][j-1] + 1;
r[1][j] = r[0][j-1];
if(f[1][j] == f[0][j]) {
r[1][j] += r[0][j];
r[1][j] %= k;
}
if(f[1][j] == f[1][j-1]) {
r[1][j] += r[1][j-1];
r[1][j] %= k;
}
} else {
f[1][j] = max(f[0][j],f[1][j-1]);
r[1][j] = 0;
if (f[1][j]==f[0][j-1]) {
r[1][j]-=r[0][j-1];
}
if (f[1][j]==f[0][j]) {
r[1][j]+=r[0][j];
}
if (f[1][j]==f[1][j-1]) {
r[1][j]+=r[1][j-1];
}
r[1][j] %= k;
}
} else {
if(a[i-1] == b[j-1]) {
f[0][j] = f[1][j-1] + 1;
r[0][j] = r[1][j-1];
if(f[0][j] == f[1][j]) {
r[0][j] += r[1][j];
r[0][j] %= k;
}
if(f[0][j] == f[0][j-1]) {
r[0][j] += r[0][j-1];
r[0][j] %= k;
}
} else {
f[0][j] = max(f[0][j-1],f[1][j]);
r[0][j] = 0;
if (f[0][j]==f[1][j-1]) {
r[0][j]-=r[1][j-1];
}
if (f[0][j]==f[1][j]) {
r[0][j]+=r[1][j];
}
if (f[0][j]==f[0][j-1]) {
r[0][j]+=r[0][j-1];
}
r[0][j] %= k;
}
}
}
}
if(la % 2) {
cout<<f[1][lb]<<endl<<r[1][lb];
} else {
cout<<f[0][lb]<<endl<<r[0][lb];
}
return 0;
}
长度可以缩减一倍,如下。
#include<iostream>
#include<cstdio>
#include<cstring>
#define k 100000000
using namespace std;
int f[2][5001],r[2][5001];
char a[5001],b[5001];
int main() {
gets(a);
gets(b);
int la = strlen(a) - 1,lb = strlen(b) - 1;
for(int j = 0; j<=lb; j++) {
r[0][j] = 1;
}
r[1][0] = 1;
int t1 = 1,t2 = 0;
for(int i = 1; i<=la; i++) {
for(int j = 1; j<=lb; j++) {
if(!(i % 2)) {
t1 = 0;
t2 = 1;
}else{
t1 = 1;
t2 = 0;
}
if(a[i-1] == b[j-1]) {
f[t1][j] = f[t2][j-1] + 1;
r[t1][j] = r[t2][j-1];
if(f[t1][j] == f[t2][j]) {
r[t1][j] += r[t2][j];
r[t1][j] %= k;
}
if(f[t1][j] == f[t1][j-1]) {
r[t1][j] += r[t1][j-1];
r[t1][j] %= k;
}
} else {
f[t1][j] = max(f[t2][j],f[t1][j-1]);
r[t1][j] = 0;
if (f[t1][j]==f[t2][j-1]) {
r[t1][j]-=r[t2][j-1];
}
if (f[t1][j]==f[t2][j]) {
r[t1][j]+=r[t2][j];
}
if (f[t1][j]==f[t1][j-1]) {
r[t1][j]+=r[t1][j-1];
}
r[t1][j] %= k;
}
}
}
if(la % 2) {
cout<<f[1][lb]<<endl<<r[1][lb];
} else {
cout<<f[0][lb]<<endl<<r[0][lb];
}
return 0;
}