1
1
extension String {
2
- func longestCommonSubsequence( other: String ) -> String {
3
-
4
- // Computes the length of the lcs using dynamic programming
5
- // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] indicates the length
6
- // of lcs between substring (0, x-1) of self and substring (0, y-1) of other.
7
- func lcsLength( other: String ) -> [ [ Int ] ] {
8
-
9
- //Matrix of size (n+1)x(m+1), algorithm needs first row and first column to be filled with 0
10
- var matrix = [ [ Int] ] ( count: self . characters. count+ 1 , repeatedValue: [ Int] ( count: other. characters. count+ 1 , repeatedValue: 0 ) )
11
-
12
- for (i, selfChar) in self . characters. enumerate ( ) {
13
- for (j, otherChar) in other. characters. enumerate ( ) {
14
- if ( otherChar == selfChar) {
15
- //Common char found, add 1 to highest lcs found so far
16
- matrix [ i+ 1 ] [ j+ 1 ] = ( matrix [ i] [ j] ) + 1
17
- }
18
- else {
19
- //Not a match, propagates highest lcs length found so far
20
- matrix [ i+ 1 ] [ j+ 1 ] = max ( matrix [ i] [ j+ 1 ] , matrix [ i+ 1 ] [ j] )
21
- }
22
- }
23
- }
24
-
25
- //Due to propagation, lcs length is at matrix[n][m]
26
- return matrix;
2
+ public func longestCommonSubsequence( other: String ) -> String {
3
+
4
+ // Computes the length of the lcs using dynamic programming.
5
+ // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] is the length
6
+ // of lcs between substring (0, x-1) of self and substring (0, y-1) of other.
7
+ func lcsLength( other: String ) -> [ [ Int ] ] {
8
+
9
+ // Create matrix of size (n+1)x(m+1). The algorithm needs first row and
10
+ // first column to be filled with 0.
11
+ var matrix = [ [ Int] ] ( count: self . characters. count+ 1 , repeatedValue: [ Int] ( count: other. characters. count+ 1 , repeatedValue: 0 ) )
12
+
13
+ for (i, selfChar) in self . characters. enumerate ( ) {
14
+ for (j, otherChar) in other. characters. enumerate ( ) {
15
+ if otherChar == selfChar {
16
+ // Common char found, add 1 to highest lcs found so far.
17
+ matrix [ i+ 1 ] [ j+ 1 ] = matrix [ i] [ j] + 1
18
+ } else {
19
+ // Not a match, propagates highest lcs length found so far.
20
+ matrix [ i+ 1 ] [ j+ 1 ] = max ( matrix [ i] [ j+ 1 ] , matrix [ i+ 1 ] [ j] )
21
+ }
27
22
}
28
-
29
- //Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are common to both strings
30
- func backtrack ( matrix : [ [ Int ] ] ) -> String {
31
- var i = self . characters . count
32
- var j = other . characters . count
33
-
34
- //charInSequence is in sync with i so we can get self[i]
35
- var charInSequence = self . endIndex
36
-
37
- var lcs = String ( )
38
-
39
- while ( i >= 1 && j >= 1 ) {
40
- //Indicates propagation without change, i.e. no new char was added to lcs
41
- if ( matrix [ i ] [ j ] == matrix [ i ] [ j - 1 ] ) {
42
- j = j - 1
43
- }
44
- //Indicates propagation without change, i.e. no new char was added to lcs
45
- else if ( matrix [ i ] [ j ] == matrix [ i - 1 ] [ j ] ) {
46
- i = i - 1
47
- //As i was subtracted, move back charInSequence
48
- charInSequence = charInSequence . predecessor ( )
49
- }
50
- //Value on the left and above are different than current cell. This means 1 was added to lcs length (line 16)
51
- else {
52
- i = i - 1
53
- j = j - 1
54
- charInSequence = charInSequence. predecessor ( )
55
-
56
- lcs . append ( self [ charInSequence ] )
57
- }
58
- }
59
-
60
- //Due to backtrack, chars were added in reverse order: reverse it back.
61
- //Append and reverse is faster than inserting at index 0
62
- return String ( lcs. characters . reverse ( ) ) ;
23
+ }
24
+
25
+ // Due to propagation, lcs length is at matrix[n][m].
26
+ return matrix
27
+ }
28
+
29
+ // Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are
30
+ // common to both strings.
31
+ func backtrack ( matrix : [ [ Int ] ] ) -> String {
32
+ var i = self . characters . count
33
+ var j = other . characters . count
34
+
35
+ // charInSequence is in sync with i so we can get self[i]
36
+ var charInSequence = self . endIndex
37
+
38
+ var lcs = String ( )
39
+
40
+ while i >= 1 && j >= 1 {
41
+ // Indicates propagation without change: no new char was added to lcs.
42
+ if matrix [ i ] [ j ] == matrix [ i ] [ j - 1 ] {
43
+ j -= 1
44
+ }
45
+ // Indicates propagation without change: no new char was added to lcs.
46
+ else if matrix [ i ] [ j ] == matrix [ i - 1 ] [ j ] {
47
+ i -= 1
48
+ // As i was decremented, move back charInSequence.
49
+ charInSequence = charInSequence. predecessor ( )
50
+ }
51
+ // Value on the left and above are different than current cell.
52
+ // This means 1 was added to lcs length (line 17).
53
+ else {
54
+ i -= 1
55
+ j -= 1
56
+ charInSequence = charInSequence . predecessor ( )
57
+ lcs. append ( self [ charInSequence ] )
63
58
}
64
-
65
- //Combine dynamic programming approach with backtrack to find the lcs
66
- return backtrack ( lcsLength ( other) )
59
+ }
60
+
61
+ // Due to backtrack, chars were added in reverse order: reverse it back.
62
+ // Append and reverse is faster than inserting at index 0.
63
+ return String ( lcs. characters. reverse ( ) )
67
64
}
68
- }
65
+
66
+ // Combine dynamic programming approach with backtrack to find the lcs.
67
+ return backtrack ( lcsLength ( other) )
68
+ }
69
+ }
0 commit comments