1+ package DynamicProgramming ;
2+
3+ /**
4+ * Given a text and wildcard pattern implement a wildcard pattern matching
5+ * algorithm that finds if wildcard is matched with text. The matching should
6+ * cover the entire text
7+ * ?-> matches single characters
8+ * *-> match the sequence of characters
9+ **/
10+
11+ /**
12+ * For calculation Time and Space Complexity. Let N be length of src and M be length of pat
13+ **/
14+
15+ public class RegexMatching {
16+
17+ // Method 1: Using Recursion
18+ // Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
19+ static boolean regexRecursion (String src , String pat ) {
20+ if (src .length () == 0 && pat .length () == 0 ) {
21+ return true ;
22+ }
23+ if (src .length () != 0 && pat .length () == 0 ) {
24+ return false ;
25+ }
26+ if (src .length () == 0 && pat .length () != 0 ) {
27+ for (int i = 0 ; i < pat .length (); i ++) {
28+ if (pat .charAt (i ) != '*' ) {
29+ return false ;
30+ }
31+ }
32+ return true ;
33+ }
34+ char chs = src .charAt (0 );
35+ char chp = pat .charAt (0 );
36+
37+ String ros = src .substring (1 );
38+ String rop = pat .substring (1 );
39+
40+ boolean ans ;
41+ if (chs == chp || chp == '?' ) {
42+ ans = regexRecursion (ros , rop );
43+ } else if (chp == '*' ) {
44+ boolean blank = regexRecursion (src , rop );
45+ boolean multiple = regexRecursion (ros , pat );
46+ ans = blank || multiple ;
47+ } else {
48+ ans = false ;
49+ }
50+ return ans ;
51+ }
52+
53+ // Method 2: Using Recursion and breaking string using virtual index
54+ // Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
55+ static boolean regexRecursion (String src , String pat , int svidx , int pvidx ) {
56+ if (src .length () == svidx && pat .length () == pvidx ) {
57+ return true ;
58+ }
59+ if (src .length () != svidx && pat .length () == pvidx ) {
60+ return false ;
61+ }
62+ if (src .length () == svidx && pat .length () != pvidx ) {
63+ for (int i = pvidx ; i < pat .length (); i ++) {
64+ if (pat .charAt (i ) != '*' ) {
65+ return false ;
66+ }
67+ }
68+ return true ;
69+ }
70+ char chs = src .charAt (svidx );
71+ char chp = pat .charAt (pvidx );
72+
73+ boolean ans ;
74+ if (chs == chp || chp == '?' ) {
75+ ans = regexRecursion (src , pat , svidx + 1 , pvidx + 1 );
76+ } else if (chp == '*' ) {
77+ boolean blank = regexRecursion (src , pat , svidx , pvidx + 1 );
78+ boolean multiple = regexRecursion (src , pat , svidx + 1 , pvidx );
79+ ans = blank || multiple ;
80+ } else {
81+ ans = false ;
82+ }
83+ return ans ;
84+ }
85+
86+ // Method 3: Top-Down DP(Memoization)
87+ // Time Complexity=0(N*M) Space Complexity=0(N*M)+Recursion Extra Space
88+ static boolean regexRecursion (String src , String pat , int svidx , int pvidx , int [][] strg ) {
89+ if (src .length () == svidx && pat .length () == pvidx ) {
90+ return true ;
91+ }
92+ if (src .length () != svidx && pat .length () == pvidx ) {
93+ return false ;
94+ }
95+ if (src .length () == svidx && pat .length () != pvidx ) {
96+ for (int i = pvidx ; i < pat .length (); i ++) {
97+ if (pat .charAt (i ) != '*' ) {
98+ return false ;
99+ }
100+ }
101+ return true ;
102+ }
103+ if (strg [svidx ][pvidx ] != 0 ) {
104+ return strg [svidx ][pvidx ] == 1 ? false : true ;
105+ }
106+ char chs = src .charAt (svidx );
107+ char chp = pat .charAt (pvidx );
108+
109+ boolean ans ;
110+ if (chs == chp || chp == '?' ) {
111+ ans = regexRecursion (src , pat , svidx + 1 , pvidx + 1 , strg );
112+ } else if (chp == '*' ) {
113+ boolean blank = regexRecursion (src , pat , svidx , pvidx + 1 , strg );
114+ boolean multiple = regexRecursion (src , pat , svidx + 1 , pvidx , strg );
115+ ans = blank || multiple ;
116+ } else {
117+ ans = false ;
118+ }
119+ strg [svidx ][pvidx ] = ans == false ? 1 : 2 ;
120+ return ans ;
121+ }
122+
123+ // Method 4: Bottom-Up DP(Tabulation)
124+ // Time Complexity=0(N*M) Space Complexity=0(N*M)
125+ static boolean regexBU (String src , String pat ) {
126+
127+ boolean strg [][] = new boolean [src .length () + 1 ][pat .length () + 1 ];
128+ strg [src .length ()][pat .length ()] = true ;
129+ for (int row = src .length (); row >= 0 ; row --) {
130+ for (int col = pat .length () - 1 ; col >= 0 ; col --) {
131+ if (row == src .length ()) {
132+ if (pat .charAt (col ) == '*' ) {
133+ strg [row ][col ] = strg [row ][col + 1 ];
134+ } else {
135+ strg [row ][col ] = false ;
136+ }
137+ } else {
138+ char chs = src .charAt (row );
139+ char chp = pat .charAt (col );
140+
141+ boolean ans ;
142+ if (chs == chp || chp == '?' ) {
143+ ans = strg [row + 1 ][col + 1 ];
144+ } else if (chp == '*' ) {
145+ boolean blank = strg [row ][col + 1 ];
146+ boolean multiple = strg [row + 1 ][col ];
147+ ans = blank || multiple ;
148+ } else {
149+ ans = false ;
150+ }
151+ strg [row ][col ] = ans ;
152+ }
153+ }
154+ }
155+ return strg [0 ][0 ];
156+ }
157+
158+ public static void main (String [] args ) {
159+
160+ String src = "aa" ;
161+ String pat = "*" ;
162+ System .out .println ("Method 1: " +regexRecursion (src , pat ));
163+ System .out .println ("Method 2: " +regexRecursion (src , pat , 0 , 0 ));
164+ System .out .println ("Method 3: " +regexRecursion (src , pat , 0 , 0 , new int [src .length ()][pat .length ()]));
165+ System .out .println ("Method 4: " +regexBU (src , pat ));
166+
167+ }
168+
169+ }
170+ // Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
171+ // Question Link : https://practice.geeksforgeeks.org/problems/wildcard-pattern-matching/1
0 commit comments