最长公共子序列

题目:给定两个字符串,求这两个字符串的最长公共子序列。

例如:cnblog 和 belogn 的最长公共子序列是blog。

                                                 0                               , i == 0 || j == 0

思路:利用动态规划的思想    C[i][j] = max{C[i-1][j], C[i][j-1]}, x[i] != y[j]

                                                 C[i-1][j-1] + 1             , x[i] == y[j]

代码如下:

 1 void LongestCommenSubSequence(char Str1[], int M, char Str2[], int N)
 2 {
 3     assert (Str1 != NULL);
 4 
 5     assert (M > 0);
 6 
 7     assert (Str2 != NULL);
 8 
 9     assert (N > 0);
10 
11     int *C = NULL;
12 
13     if (NULL == (C = (int *)malloc ((M + 1) * (N + 1) * sizeof (int))))
14     {
15         printf ("Fail to malloc space to C.\n");
16         exit (1);
17     }
18 
19     for (int i = 0; i <= M; ++i)
20     {
21         for (int j = 0; j <= N; ++j)
22         {
23             if ((0 == i) || (0 == j))
24             {
25                 // 初始化第0行和第列
26                 C[i * (N + 1) + j] = 0;
27                 continue;
28             }
29 
30             if (Str1[i - 1] == Str2[j - 1])
31             {
32                 // C[i][j] = C[i - 1][j-1] + 1
33                 C[i * (N + 1) + j] = C[(i - 1) * (N + 1) + (j - 1)] + 1;
34             }
35             else
36             {
37                 // C[i][j] = max{C[i-1][j], C[i][j-1]}
38                 C[i * (N + 1) + j] = C[(i - 1) * (N + 1) + j] > C[i * (N + 1) + (j - 1)] ? C[(i - 1) * (N + 1) + j] : C[i * (N + 1) + (j - 1)];
39             }
40         }
41     }
42 
43     // 定义一个栈用来保存最长序列,因为是回溯法找,最先找到的字符要最后输出
44     char Stack[MAX];
45     int nTop = -1;
46     int i = M;
47     int j = N;
48 
49     bool bFlag = true;
50 
51     while (bFlag)
52     {
53         if ((C[i * (N + 1) + j] > C[(i - 1) * (N + 1) + (j - 1)]) && (C[i * (N + 1) + j] > C[(i - 1) * (N + 1) + j]))
54         {
55             // 说明Str1[i] == Str2[j],入栈
56             Stack[++nTop] = Str1[i - 1];
57         }
58 
59         if ((0 == C[(i - 1) * (N + 1) + (j - 1)]) && (0 == C[(i - 1) * (N + 1) + j]))
60         {
61             // 上面和左上角元素都为0,说明没有必要再回溯
62             bFlag = false;
63             continue;
64         }
65 
66         // 寻找回溯的方向
67         if (C[(i - 1) * (N + 1) + j] > C[(i - 1) * (N + 1) + (j - 1)])
68         {
69             // 上面大,就往上面走
70             --i;
71         }
72         else
73         {
74             // 否则都往左上角方向走
75             --i;
76             --j;
77         }
78     }
79 
80     if (-1 == nTop)
81     {
82         printf ("这两个字符串没有公共子序列.\n");
83         return;
84     }
85 
86     printf ("这两个字符串的最长公共子序列为:\n");
87 
88     while (nTop >= 0)
89     {
90         printf ("%c", Stack[nTop--]);
91     }
92 
93     printf ("\n");
94 }

测试结果:

  

原文地址:https://www.cnblogs.com/ldjhust/p/3059674.html