hrbust 1598 求最长公共子序列

当数组长度p,q范围高达10000所以O(pq)的算法会超时。注意到序列中所有元素各不相同,因此可以把A串重新编号为1~p,例如:

A={1 7 5 4 8 3 2},B={1 4 3 5 6 2 8 7}  把A重新编号后:

A={1 2 3 4 5 6 7},B={1 4 6 3 0 7 5 2} 其中0表示在A中没有出现过,因为没有出现过所以就不用考虑了,肯定不在最长公共子序列中。对于新的A,B序列只需求B的最长递增子序列即可。因为n的范围较大,所以需要用到O(nlogn)的方法求最长递增子序列(二分)。

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 const int MAX = 10001;
 5 
 6 int main(void)
 7 {
 8     int t;
 9     int p;
10     int q;
11     int A[MAX];
12     int B[MAX];
13     int res;
14     scanf("%d", &t);
15 
16     while (t--)
17     {
18         int x;
19         int provi[MAX];
20         scanf("%d%d", &p, &q);
21 
22         memset(provi, 0, sizeof(provi));
23 
24         for (int i=1; i<=p; i++)
25         {
26             scanf("%d", &x);
27             provi[x] = i;
28         }
29         int k = 0;
30         for (int i=1; i<=q; i++)//为什么这样写自己的好好想想写写看
31         {
32             scanf("%d", &x);
33             if (provi[x] != 0)
34             {
35                 A[k++] = provi[x];
36             }
37         }
38         B[0] = A[0];
39         res = 1;
40         for (int i=1; i<k; i++)
41         {
42             int left = 0;
43             int right = res;
44             while (left < right)
45             {
46                 int mid = (left + right) / 2;
47                 if (A[i] > B[mid])
48                 {
49                     left = mid + 1;
50                 }
51                 else
52                 {
53                     right = mid;
54                 }
55             }
56             B[left] = A[i];
57             if (left >= res)
58             {
59                 res++;
60             }
61         }
62         printf("%d\n", res);
63     }
64     return 0;
65 }

 

 

 

posted @ 2012-12-10 22:28  尔滨之夏  阅读(273)  评论(0编辑  收藏  举报