diff --git a/include/solution/10.h b/include/solution/10.h new file mode 100644 index 0000000..7ba8cd3 --- /dev/null +++ b/include/solution/10.h @@ -0,0 +1,15 @@ +// This file is generated by mkfile.py +// Date: 2026-06-25 + +#ifndef INC_10_H +#define INC_10_H +#ifdef __cplusplus +extern "C" +{ +#endif +#include + bool isMatch(char *s, char *p); +#ifdef __cplusplus +} +#endif +#endif // INC_10_H diff --git a/src/10.c b/src/10.c new file mode 100644 index 0000000..cd313c5 --- /dev/null +++ b/src/10.c @@ -0,0 +1,58 @@ +// This file is generated by mkfile.py +// Date: 2026-06-25 + +#include +#include +#include + +bool char_march(char s, char p) +{ + return p == '.' || s == p; +} + +bool isMatch(char *s, char *p) +{ + size_t m = strlen(s); + size_t n = strlen(p); + + bool **dp = malloc(sizeof(bool *) * (m + 1)); + for (size_t i = 0; i < (m + 1); i++) + { + dp[i] = malloc(sizeof(bool) * (n + 1)); + memset(dp[i], false, sizeof(bool) * (n + 1)); + } + dp[0][0] = true; + + // s is empty + for (size_t j = 2; j <= n; j++) + { + if (p[j - 1] == '*') + dp[0][j] = dp[0][j - 2]; + } + + for (size_t i = 1; i <= m; i++) + { + for (size_t j = 1; j <= n; j++) + { + if (p[j - 1] != '*') + { + dp[i][j] = dp[i - 1][j - 1] && char_march(s[i - 1], p[j - 1]); + } + else + { + dp[i][j] = dp[i][j - 2]; + if (char_march(s[i - 1], p[j - 2])) + dp[i][j] = dp[i][j] || dp[i - 1][j]; + } + } + } + + bool matched = dp[m][n]; + + for (size_t i = 0; i <= m; i++) + { + free(dp[i]); + } + free(dp); + return matched; +} diff --git a/tests/test_10.cpp b/tests/test_10.cpp new file mode 100644 index 0000000..c08c17e --- /dev/null +++ b/tests/test_10.cpp @@ -0,0 +1,90 @@ +// This file is generated by mkfile.py +// Date: 2026-06-25 + +#include +#include + +#include +#include + +class RegexMatchTest : public ::testing::Test +{ + protected: + void AssertIsMatch(const std::string &s, const std::string &p, bool expected) + { + std::vector s_buffer(s.begin(), s.end()); + std::vector p_buffer(p.begin(), p.end()); + s_buffer.push_back('\0'); + p_buffer.push_back('\0'); + + EXPECT_EQ(isMatch(s_buffer.data(), p_buffer.data()), expected); + } +}; + +TEST_F(RegexMatchTest, Example1) +{ + AssertIsMatch("aa", "a", false); +} + +TEST_F(RegexMatchTest, Example2) +{ + AssertIsMatch("aa", "a*", true); +} + +TEST_F(RegexMatchTest, Example3) +{ + AssertIsMatch("ab", ".*", true); +} + +TEST_F(RegexMatchTest, Example4) +{ + AssertIsMatch("aab", "c*a*b", true); +} + +TEST_F(RegexMatchTest, Example5) +{ + AssertIsMatch("mississippi", "mis*is*p*.", false); +} + +TEST_F(RegexMatchTest, EmptyString) +{ + AssertIsMatch("", "", true); + AssertIsMatch("", "a*", true); + AssertIsMatch("", "c*c*", true); + AssertIsMatch("", ".", false); +} + +TEST_F(RegexMatchTest, DotMatchesAnySingleCharacter) +{ + AssertIsMatch("ab", ".b", true); + AssertIsMatch("ab", "..", true); + AssertIsMatch("ab", ".", false); +} + +TEST_F(RegexMatchTest, StarCanMatchZeroCharacters) +{ + AssertIsMatch("b", "a*b", true); + AssertIsMatch("ab", "ab*c", false); + AssertIsMatch("a", "ab*", true); +} + +TEST_F(RegexMatchTest, StarCanMatchMultipleCharacters) +{ + AssertIsMatch("aaa", "a*", true); + AssertIsMatch("aaaaab", "a*b", true); + AssertIsMatch("bbbba", ".*a*a", true); +} + +TEST_F(RegexMatchTest, MustMatchWholeString) +{ + AssertIsMatch("abcd", "d*", false); + AssertIsMatch("abc", ".*d", false); + AssertIsMatch("aaa", "aaaa", false); +} + +TEST_F(RegexMatchTest, ComplexBacktrackingCases) +{ + AssertIsMatch("aaa", "ab*a*c*a", true); + AssertIsMatch("a", ".*..a*", false); + AssertIsMatch("mississippi", "mis*is*ip*.", true); +}