第二次刷这个题了,动归,空间上从原来的 n^2 到现在的 2n,做了优化
PS:原来的代码找不到了,从网上download了一个,思想是一样的
#include<iostream>
using namespace std;
const int MAXN = 30;
int aim[MAXN], now[MAXN], f[MAXN][MAXN];
int max(int x, int y) {return (x > y) ? x : y;}
int main()
{
int n, i, j, tmp;
cin >> n;
for (i = 0; i < n; i++)
{
cin >> tmp;
aim[tmp-1] = i+1;
}
while (cin >> tmp)
{
now[tmp-1] = 1;
for (i = 1; i < n; i++)
{
cin >> tmp;
now[tmp-1] = i+1;
}
memset(f, 0, sizeof(f));
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (aim[i] == now[j]) f[i+1][j+1] = f[i][j]+1;
else f[i+1][j+1] = max(f[i][j+1], f[i+1][j]);
cout << f[n][n] << endl;
}
}
可以看到,f[i][j] 表示的是模版串第 i 个和需要匹配的字符串的第 j 个所能匹配的最大长度。
优化后的代码,时间复杂度仍然是 n^2
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int n, max;
int year[21], dp[21], a[21];
int i, j;
int ans, tmp;
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%d", &tmp);
year[tmp-1] = i+1;
}
while(scanf("%d", &tmp) != EOF) {
memset(dp, 0, sizeof(dp));
a[tmp-1] = 1;
for(i = 1; i < n; i++) {
scanf("%d", &tmp);
a[tmp-1]=i+1;
}
for(i = 0; i < n; i++) {
max = 0;
for(j = 0; j < n; j++) {
if(max < dp[j]) {
max = dp[j];
}
if(a[j] == year[i]) {
dp[j] = max+1;
}
}
}
max = 0;
for(i = 0; i < n; i++) {
// printf("%d ", dp[i]);
if(max < dp[i]) {
max = dp[i];
}
}
printf("%d\n", max);
}
return 0;
}
只用一个一维的 dp 数组记录匹配串的第 j 个所能匹配的最大长度。