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 }