Skip to content

Commit 05c65c1

Browse files
Add wildcard pattern matching (TheAlgorithms#2441)
1 parent 7cc96f9 commit 05c65c1

1 file changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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

Comments
 (0)