Common Subsequence (longest Common Subsequence + Dynamic Planning) hdu1159 classic
Common Subsequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission (s): 29329 Accepted Submission (s): 13174
Problem Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = Another sequence Z = Is a subsequence of X if there exists a strictly increasing sequence Of indices of X such that for all j = 1, 2 ,..., k, xij = zj. for example, Z = is a subsequence of X = with index sequence <1, 2, 4, 6>. given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
The program input is from a text file. each data set in the file contains two strings representing the given sequences. the sequences are separated by any number of white spaces. the input data are correct. for each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.
Sample Input
abcfbc abfcabprogramming contest abcd mnp
Sample Output
420
Source Southeastern Europe 2003
Link: http://acm.hdu.edu.cn/showproblem.php? Pid = 1, 1159
The longest common substring of two strings.
Idea: dynamic planning.
The longest public subsequence is a classic issue of dynamic planning. I am learning about dynamic planning recently. So I will try it here.
This problem occurs in the introduction to algorithms as an example of Dynamic Planning Algorithms.
Dynamic Planning, as we all know, the first step is to find Sub-problems, that is, to break down a big problem into sub-problems. Here we set two strings A, B, A = a0, a1, a2,..., am-1, B = b0, b1, b2,..., bn-1.
(1) If am-1 = bn-1, the current longest common subsequence is a0, a1 ,..., am-2 and b0, b1 ,..., the longest common subsequence of bn-2 with am-1 and. The length is a0, a1,..., am-2 and b0, b1,..., the length of the longest common subsequence of the bn-2 + 1.
(2) If am-1! = Bn-1, then the longest common subsequence is max (a0, a1 ,..., am-2 and b0, b1 ,..., common subsequences of bn-1, a0, a1 ,..., am-1 and b0, b1 ,..., the common subsequence of bn-2)
If the preceding description is represented by a mathematical formula, a two-dimensional array c [] [] is introduced, where c [I] [j] records the LCS length of X [I] AND Y [j, B [I] [j] records the value of c [I] [j] through which a subproblem is obtained, that is, the search direction.
In this way, we can sum up the recursive expression of this problem:
According to the idea of dynamic planning, solving the problem is actually a bottom-up computing process for sub-problems. Here, when c [I] [j] is calculated, c [I-1] [J-1], c [I-1] [j], c [I] [J-1] has been calculated, in this way, we can find c [I] [j] based on the values of X [I] AND Y [j] based on the recursion above, at the same time, the path is recorded in B [I] [j] (the path has only three middle directions: top left, top left, and top, such ).
The time complexity of computing the c [] [] matrix is O (m * n). The process of finding the longest common subsequence Based on the B [] [] Matrix, since each call moves at least one step up or to the left, I = 0 or j = 0 is required at most (m + n) times, that is, the algorithm time complexity is O (m + n ).
# Include
# Include
# Include
# Includeusing namespace std; int map [10005] [10005]; string str1, str2; int len1, len2; // Longest Common subsequence/*** recursive solution: 0 if (I = 0 | j = 0 ); map [I] [j] = map [I-1] [J-1] if (I> 0 & j> 0 & str1 [I] = str2 [j]) max (map [I-1] [j], map [I] [J-1]) if (I> 0 & j> 0 & str1 [I]! = Str2 [j]) * // ***** recursive timeout! Int LCS (int x, int y) {if (x <0 | y <0) return 0; if (str1 [x] = str2 [y]) return LCS (x-1, Y-1) + 1; else return max (LCS (x-1, y), LCS (x, Y-1);} */int main () {while (cin> str1> str2) {len1 = str1.length ()-1; len2 = str2.length ()-1; // printf (% d, LCS (len1, len2);/*** non-recursive solution LCS */for (int I = 0; I <= len1 + 1; I ++) {for (int j = 0; j <= len2 + 1; j ++) {if (I = 0 | j = 0) {map [I] [j] = 0; continue ;} if (str1 [I-1] = str2 [J-1]) {map [I] [j] = map [I-1] [J-1] + 1 ;} else {map [I] [j] = max (map [I-1] [j], map [I] [J-1]) ;}} printf (% d, map [len1 + 1] [len2 + 1]);} return 0 ;}
There is also a way to optimize the space by rolling the array! The Code is also attached here. It is useful when you do not need to record paths!
# Include
# Include
# Include
# Includeusing namespace std; int map [2] [10005]; string str1, str2; int len1, len2; // The Longest Common subsequence int LCS (int x, int y) {for (int I = 0; I <= x; I ++) {for (int j = 0; j <= y + 1; j ++) {if (I = 0 | j = 0) {map [I % 2] [j] = 0; continue ;} if (str1 [I-1] = str2 [J-1]) {map [I % 2] [j] = map [(I-1) % 2] [J-1] + 1 ;} else {map [I % 2] [j] = max (map [(I-1) % 2] [j], map [I % 2] [J-1]); }}} int main () {while (cin> str1> str2) {len1 = str1.length (); len2 = str2.length (); LCS (len1, len2); printf (% d, map [len1% 2] [len2]);} return 0 ;}