第二次刷这个题了,动归,空间上从原来的 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 个所能匹配的最大长度。