1+ '''
2+ Interleaving Strings
3+
4+ Given are three strings A, B and C.
5+ C is said to be interleaving of A and B, if:
6+ - it contains all characters of A and B, and
7+ - order of all characters from A and B is preserved in C
8+ Your task is to count in how many ways C can be formed by interleaving of A and B.
9+
10+ Input: A='xy', B= 'xz', C: 'xxyz'
11+ Output: 2
12+ Output explanation:
13+ 1) Take 'x' from A, then 'x' from B, then 'y' from A and at the end 'z' from B.
14+ 2) Take 'x' from B, then 'x' from A, then 'y' from A and at the end 'z' from B.
15+
16+ =========================================
17+ 2D Dynamic programming solution.
18+ Time Complexity: O(N*M)
19+ Space Complexity: O(N*M)
20+ 1D Dynamic programming solution. Only the last two rows from the whole matrix are used, but that could be represented using only 1 row.
21+ Time Complexity: O(N*M)
22+ Space Complexity: O(M)
23+ '''
24+
25+ ##############
26+ # Solution 1 #
27+ ##############
28+
29+ def interleaving_strings_1 (A , B , C ):
30+ nA , nB , nC = len (A ), len (B ), len (C )
31+ if nA + nB != nC :
32+ return 0
33+
34+ dp = [[0 for j in range (nB + 1 )] for i in range (nA + 1 )]
35+
36+ # starting values
37+ dp [0 ][0 ] = 1
38+
39+ for i in range (1 , nA + 1 ):
40+ if A [i - 1 ] == C [i - 1 ]:
41+ # short form of if A[i - 1] == C[i - 1] and dp[i - 1][0] == 1
42+ # dp[i][0] and dp[0][1] can be only 0 or 1
43+ dp [i ][0 ] = dp [i - 1 ][0 ]
44+
45+ for i in range (1 , nB + 1 ):
46+ if B [i - 1 ] == C [i - 1 ]:
47+ dp [0 ][i ] = dp [0 ][i - 1 ]
48+
49+ # run dp
50+ for i in range (1 , nA + 1 ):
51+ for j in range (1 , nB + 1 ):
52+ if A [i - 1 ] == C [i + j - 1 ]:
53+ # look for the dp value from the previous position
54+ dp [i ][j ] += dp [i - 1 ][j ]
55+ if B [j - 1 ] == C [i + j - 1 ]:
56+ # look for the dp value from the previous position
57+ dp [i ][j ] += dp [i ][j - 1 ]
58+
59+ return dp [nA ][nB ]
60+
61+
62+ ##############
63+ # Solution 2 #
64+ ##############
65+
66+ def interleaving_strings_2 (A , B , C ):
67+ nA , nB , nC = len (A ), len (B ), len (C )
68+ if nA + nB != nC :
69+ return 0
70+
71+ dp = [0 for j in range (nB + 1 )]
72+
73+ # starting values
74+ dp [0 ] = 1
75+
76+ for i in range (1 , nB + 1 ):
77+ if B [i - 1 ] == C [i - 1 ]:
78+ dp [i ] = dp [i - 1 ]
79+
80+ # run dp
81+ for i in range (1 , nA + 1 ):
82+ if A [i - 1 ] != C [i - 1 ]:
83+ # reset the value
84+ dp [0 ] = 0
85+
86+ for j in range (1 , nB + 1 ):
87+ if A [i - 1 ] != C [i + j - 1 ]:
88+ # reset the value
89+ dp [j ] = 0
90+ if B [j - 1 ] == C [i + j - 1 ]:
91+ dp [j ] += dp [j - 1 ]
92+
93+ return dp [nB ]
94+
95+
96+ ###########
97+ # Testing #
98+ ###########
99+
100+ # Test 1
101+ # Correct result => 2
102+ print (interleaving_strings_1 ('xy' , 'xz' , 'xxyz' ))
103+
104+ # Test 2
105+ # Correct result => 2
106+ print (interleaving_strings_2 ('xy' , 'xz' , 'xxyz' ))
0 commit comments