DP3_最长公共子序列

 1 using System;
 2 namespace ConsoleApplication2
 3 {
 4     public class Program
 5     {
 6         static int[,] martix;
 7 
 8         static string str1 = "cnblogs";
 9         static string str2 = "belong";
10 
11         static void Main(string[] args)
12         {
13             martix = new int[str1.Length + 1, str2.Length + 1];
14 
15             LCS(str1, str2);
16 
17             //只要拿出矩阵最后一个位置的数字即可
18             Console.WriteLine("当前最大公共子序列的长度为:{0}", martix[str1.Length, str2.Length]);
19 
20             Console.Read();
21         }
22 
23         static void LCS(string str1, string str2)
24         {
25             //初始化边界,过滤掉0的情况
26             for (int i = 0; i <= str1.Length; i++)
27                 martix[i, 0] = 0;
28 
29             for (int j = 0; j <= str2.Length; j++)
30                 martix[0, j] = 0;
31 
32             //填充矩阵
33             for (int i = 1; i <= str1.Length; i++)
34             {
35                 for (int j = 1; j <= str2.Length; j++)
36                 {
37                     //相等的情况
38                     if (str1[i - 1] == str2[j - 1])
39                     {
40                         martix[i, j] = martix[i - 1, j - 1] + 1;
41                     }
42                     else
43                     {
44                         //比较“左边”和“上边“,根据其max来填充
45                         if (martix[i - 1, j] >= martix[i, j - 1])
46                             martix[i, j] = martix[i - 1, j];
47                         else
48                             martix[i, j] = martix[i, j - 1];
49                     }
50                 }
51             }
52         }
53     }
54 }
View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int MAX(int a, int b)
 6 {
 7     return a>b?a:b;
 8 }
 9 int f(char* x, char* y)
10 {
11     if(strlen(x)==0) return 0;
12     if(strlen(y)==0) return 0;
13     if(*x == *y) return f(x+1,y+1)+1;
14     return  MAX(f(x,y+1),f(x+1,y));
15 }
16 int main()
17 {
18     printf("%d\n", f("ac","abcd")); //2
19     printf("%d\n", f("acebbcde1133","xya33bc11de")); //5
20     return 0;
21 }
View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int LCSLength(char x[], char y[],int m, int n)
 6 {
 7     /* 计算最长公共子序列的长度 */
 8     int L[m+1][n+1],i, j;
 9     for (i = 0; i <= m; i++) L[i][0] = 0;
10     for (i = 0; i <= n; i++) L[0][i] = 0;
11 
12     for (i = 1; i <= m; i++)
13     {
14         for (j = 1; j <= n; j++)
15         {
16             if (x[i]==y[j])
17                 L[i][j]=L[i-1][j-1]+1;
18             else if (L[i-1][j]>= L[i][j-1])
19                 L[i][j]= L[i-1][j];
20             else
21                 L[i][j]= L[i][j-1];
22 //            if (x[i]==y[j])
23 //                L[i][j]=L[i-1][j-1]+1;
24 //            else
25 //            {
26 //                if (L[i-1][j]>= L[i][j-1])
27 //                    L[i][j]= L[i-1][j];
28 //                else
29 //                    L[i][j]= L[i][j-1];
30 //            }
31         }
32     }
33     return L[m][n];
34 }
35 int main()
36 {
37     char a[100] = "cnblogs";
38     char b[100] = "belong";
39     cout << LCSLength(a, b, strlen(a), strlen(b)) << endl;
40     return 0;
41 }
View Code


概念:

      举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出

子序列不见得一定是连续的,连续的那是子串。

分析:

既然是经典的题目肯定是有优化空间的,并且解题方式是有固定流程的,这里我们采用的是矩阵实现,也就是二维数组。

第一步:先计算最长公共子序列的长度。

第二步:根据长度,然后通过回溯求出最长公共子序列。

现有两个序列X={x1,x2,x3,...xi},Y={y1,y2,y3,....,yi},

设一个C[i,j]: 保存Xi与Yj的LCS的长度。

动态规划的一个重要性质特点就是解决“子问题重叠”的场景,可以有效的避免重复计算,根据上面的公式其实可以发现C[i,j]一直保存着当前(Xi,Yi)的最大子序列长度

 

posted @ 2015-04-09 13:33  PastLIFE  阅读(151)  评论(0编辑  收藏  举报