洛谷 P1439 【模板】最长公共子序列

题目传送门

解题思路:

先是朴素做法,f[i][j]表示字符串A前i位和字符串B前j位的最长公共子序列,

当a[i] == b[j]时,f[i][j]=f[i-1][j-1] + 1; 如果不相等,f[i][j]=max(f[i-1[j],f[i][j-1);

时间复杂度是O(nm)的,近似O(n^2).

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int n,a[100001],b[100001],f[1001][1001];
 5 
 6 int main() {
 7     cin >> n;
 8     for(int i = 1;i <= n; i++) 
 9         cin >> a[i];
10     for(int i = 1;i <= n; i++)
11         cin >> b[i];
12     for(int i = 1;i <= n; i++)
13         for(int x = 1;x <= n; x++)
14             if(a[i] == b[x])
15                 f[i][x] = max(f[i-1][x-1] + 1, f[i][x]);
16             else
17                 f[i][x] = max(f[i-1][x], f[i][x-1]);
18     cout << f[n][n] <<endl;
19     return 0;
20 }
朴素做法50分

以上做法对于本题只能的50分,所以就要想办法优化,怎么优化呢?

来一个c数组,其中c[i]存的是a[i]在b中的位置,举个例子:

a: 1 3 4 5 2 7

b: 2 4 5 1 7 3

c: 4 6 2 3 1 5 

然后在c中求最长上升子序列,即为答案

时间复杂度为O(n log n)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 int n,c[100001],f[100001],len; 
 8 struct kkk{
 9     int o,p;
10 }a[100001],b[100001];
11 
12 inline bool cmp(kkk s,kkk d) {
13     return s.o < d.o;
14 }
15 
16 int main() {
17     scanf("%d",&n);
18     for(int i = 1;i <= n; i++) {
19         scanf("%d",&a[i].o);
20         a[i].p = b[i].p = i;
21     }
22     for(int i = 1;i <= n; i++)
23         scanf("%d",&b[i].o);
24     sort(a+1,a+n+1,cmp);
25     sort(b+1,b+n+1,cmp);
26     for(int i = 1;i <= n; i++)
27         c[a[i].p] = b[i].p;
28     for(int i = 1;i <= n; i++) {
29         if(c[i] > f[len])
30             f[++len] = c[i];
31         else {
32             int u = lower_bound(f+1,f+len+1,c[i]) - f;
33             f[u] = c[i];
34         }
35     }
36     printf("%d",len);
37     return 0;
38 }
100分
原文地址:https://www.cnblogs.com/lipeiyi520/p/12319633.html