@@ -26,74 +26,49 @@ namespace Utils
26
26
#pragma warning(disable: 4505)
27
27
#endif
28
28
29
- static bool patternMatch (const std::string& entryName, const std::string& pattern)
30
- {
31
- auto match { true };
32
- // Match the glob pattern without regex
33
- auto patternPos { 0u };
29
+ static bool patternMatch (const std::string& entryName, const std::string& pattern)
30
+ {
31
+ std::string_view entry (entryName);
32
+ std::string_view pat (pattern);
33
+
34
+ // Dynamic programming approach - create a table for memoization
35
+ // dp[i][j] is true if the first i characters of entry match the first j characters of pattern
36
+ std::vector<std::vector<bool >> dp (entry.size () + 1 , std::vector<bool >(pat.size () + 1 , false ));
37
+
38
+ // Empty pattern matches empty string
39
+ dp[0 ][0 ] = true ;
34
40
35
- for (auto i { 0u }; i < entryName.size (); ++i)
41
+ // Handle patterns like "*", "*a", "a*b*" etc. where '*' can match empty strings
42
+ for (size_t j = 1 ; j <= pat.size (); ++j)
43
+ {
44
+ if (pat[j - 1 ] == ' *' )
36
45
{
37
- if (patternPos < pattern.size ())
38
- {
39
- // 'x' matches 'x'
40
- if (entryName.at (i) == pattern.at (patternPos))
41
- {
42
- ++patternPos;
43
- }
44
- // '*' matches any number of characters
45
- else if (pattern.at (patternPos) == ' *' )
46
- {
47
- // '*' matches zero characters
48
- if (patternPos + 1 < pattern.size () && pattern.at (patternPos + 1 ) == entryName.at (i))
49
- {
50
- ++patternPos;
51
- --i;
52
- }
53
- // '*' matches one or more characters
54
- else if (patternPos + 1 == pattern.size ())
55
- {
56
- break ;
57
- }
58
- }
59
- // '?' matches any single character
60
- else if (pattern.at (patternPos) == ' ?' )
61
- {
62
- ++patternPos;
63
- }
64
- // No match
65
- else
66
- {
67
- match = false ;
68
- break ;
69
- }
70
- }
71
- else
72
- {
73
- match = false ;
74
- break ;
75
- }
46
+ dp[0 ][j] = dp[0 ][j - 1 ];
76
47
}
48
+ }
77
49
78
- // if the pattern is not fully matched, check if the remaining characters are '*'
79
- // and if so, the match is successful.
80
- while (match && patternPos < pattern.size ())
50
+ // Fill the dp table
51
+ for (size_t i = 1 ; i <= entry.size (); ++i)
52
+ {
53
+ for (size_t j = 1 ; j <= pat.size (); ++j)
81
54
{
82
- // '*' matches zero characters
83
- if (pattern.at (patternPos) == ' *' )
55
+ if (pat[j - 1 ] == ' *' )
84
56
{
85
- ++patternPos;
57
+ // '*' can match 0 or more characters
58
+ // Either ignore '*' (dp[i][j-1]) or use '*' to match current character (dp[i-1][j])
59
+ dp[i][j] = dp[i][j - 1 ] || dp[i - 1 ][j];
86
60
}
87
- // No match
88
- else
61
+ else if (pat[j - 1 ] == ' ?' || entry[i - 1 ] == pat[j - 1 ])
89
62
{
90
- match = false ;
63
+ // '?' matches any single character, or exact character match
64
+ dp[i][j] = dp[i - 1 ][j - 1 ];
91
65
}
92
66
}
93
-
94
- return match;
95
67
}
96
68
69
+ return dp[entry.size ()][pat.size ()];
70
+ }
71
+
97
72
#ifdef __GNUC__
98
73
#pragma GCC diagnostic pop
99
74
#endif
0 commit comments