1408. String Matching in an Array
1408. String Matching in an Array
[Problem]
Intuition
This can be achieved using either a brute force approach or the more efficient KMP algorithm for substring matching.
Although brute force will work in the question as the constraints are small, we would discuss both the approaches here.
1 2 3
Constraints: 1 <= words.length <= 100 1 <= words[i].length <= 30
Resources
Before attempting this problem, consider reviewing MY TAKE ON THE KMP ALGORITHM for a clear explanation of the KMP algorithm approach.
- Additional resources to learn about the KMP Algorithm:
- Few questions to practice KMP algorithm are:
Approach 1: Brute Force
- Compare each string with all other strings in the array.
- Check if one string is a substring of another using Java’s
.contains()
method. - Add the substring to the result list if not already present.
Complexity Analysis
- Time Complexity: O(n^2 * m)
n
: Number of strings in the array.m
: Average length of the strings.
- Space Complexity: O(k)
k
: Space used to store the result list.
Approach 2: KMP Algorithm
- For each string, check if it is a substring of another string using the precomputed LPS (Longest Prefix Suffix) array.
Avoid duplicates by checking if the substring is already in the result list.
- Time Complexity: O(n^2 + n * m)
n^2
: Traversal of the string pairs.n * m
: KMP substring matching.
- Space Complexity: O(k + m)
k
: Space used to store the result list.m
: Space used for the LPS array.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
class Solution {
public List<String> stringMatching(String[] words) {
// Brute force (uncomment for use)
// return bruteForce(words);
// KMP algorithm
int n = words.length;
List<String> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
String strI = words[i];
for (int j = 0; j < n; j++) {
if (i != j) {
String strJ = words[j];
// Check if strI is a substring of strJ using KMP
if (!res.contains(strI) && isSubstringKMP(strI, strJ)) {
res.add(strI);
}
}
}
}
return res;
}
// KMP Algorithm for substring matching
public boolean isSubstringKMP(String pat, String text) {
int patLen = pat.length();
int textLen = text.length();
if (patLen > textLen) {
return false;
}
int[] lps = new int[patLen];
computeLPS(pat, lps);
int i = 0; // text pointer
int j = 0; // pattern pointer
while (i < textLen) {
if (text.charAt(i) == pat.charAt(j)) {
i++;
j++;
if (j == patLen) {
return true; // Pattern found
}
} else {
if (j == 0) {
i++;
} else {
j = lps[j - 1];
}
}
}
return false;
}
// Compute the LPS array for KMP
public void computeLPS(String pat, int[] lps) {
int len = 0;
int i = 1;
lps[0] = 0;
while (i < pat.length()) {
if (pat.charAt(i) == pat.charAt(len)) {
len++;
lps[i] = len;
i++;
} else {
if (len == 0) {
lps[i] = 0;
i++;
} else {
len = lps[len - 1];
}
}
}
}
// Brute Force approach
public List<String> bruteForce(String[] words) {
int n = words.length;
List<String> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
String strI = words[i];
for (int j = 0; j < n; j++) {
if (i != j) {
String strJ = words[j];
if (strI.contains(strJ) && !res.contains(strJ)) {
res.add(strJ);
}
}
}
}
return res;
}
}
This post is licensed under CC BY 4.0 by the author.