天天看点

nyoj 36-最长公共子序列 (动态规划,DP, LCS)

36-最长公共子序列

内存限制:64MB

时间限制:3000ms

Special Judge: No

accepted:18

submit:38

题目描述:

咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。

tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

输入描述:

第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.      

输出描述:

每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。      

样例输入:

复制

2
asdf
adfsd
123abc
abc123abc      

样例输出:

3
6

分析:
  ①、类似于这种最长字串问题需要以一个串作为基串,另一个串则从左到右计算对应该位置的最大长度
  ②、即就是局部最优的情况下累积,就是全局最优
  ③、所以,以一个二维数组作为DP数组,我们要做的就是根据状态方程得出最大值

核心代码(模板):

        
1 for(int i = 1; i <= len1; ++ i)
2 {
3     for(int j = 1; j <= len2; ++ j)
4     {
5         if(s1[i] == s2[j]) dp[i][j] = dp[i-1][j-1] + 1;
6         else dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
7     }
8 }      
1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <stack>
 7 #include <map>
 8 #include <queue>
 9 #include <set>
10 
11 using namespace std;
12 const int MAXN = 1010;
13 int dp[MAXN][MAXN];
14 
15 int main()
16 {
17     int t;
18     scanf("%d", &t);
19     while(t --)
20     {
21         char s1[MAXN], s2[MAXN];
22         int len1, len2;
23         memset(dp, 0, sizeof(dp));
24         scanf("%s%s", s1 + 1, s2 + 1);
25         len1 = strlen(s1 + 1), len2 = strlen(s2 + 1);
26 
27         for(int i = 1; i <= len1; ++ i)
28         {
29             for(int j = 1; j <= len2; ++ j)
30             {
31                 if(s1[i] == s2[j])
32                     dp[i][j] = dp[i-1][j-1] + 1;
33                 else
34                     dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
35             }
36         }
37 
38         printf("%d\n", dp[len1][len2]);
39     }
40     return 0;
41 }      

Aspire to inspire until I expire