From b63fdb775dce77db00bac59b890425812b1efacc Mon Sep 17 00:00:00 2001 From: Jeffrey Hsu Date: Fri, 26 Jun 2026 15:04:19 +0800 Subject: [PATCH] 32 --- include/solution/32.h | 14 ++++++++ src/32.c | 69 ++++++++++++++++++++++++++++++++++++++++ tests/test_32.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 include/solution/32.h create mode 100644 src/32.c create mode 100644 tests/test_32.cpp diff --git a/include/solution/32.h b/include/solution/32.h new file mode 100644 index 0000000..c26b3e3 --- /dev/null +++ b/include/solution/32.h @@ -0,0 +1,14 @@ +// This file is generated by mkfile.py +// Date: 2026-06-26 + +#ifndef INC_32_H +#define INC_32_H +#ifdef __cplusplus +extern "C" +{ +#endif + int longestValidParentheses(char *s); +#ifdef __cplusplus +} +#endif +#endif // INC_32_H diff --git a/src/32.c b/src/32.c new file mode 100644 index 0000000..abf0eb6 --- /dev/null +++ b/src/32.c @@ -0,0 +1,69 @@ +// This file is generated by mkfile.py +// Date: 2026-06-26 + +#include + +#include +#include + +#define max(x, y) ((x) > (y) ? (x) : (y)) + +int longestValidParentheses(char *s) +{ + int result = 0; + int m = strlen(s); + + if (m < 2) + return result; + + int *dp = malloc(sizeof(int) * m); + memset(dp, 0, sizeof(int) * m); + + // i: current index, we skipped 0 because one char can not + // be paired + // dp[i]: use i as the end of string, see how much parentheses + // can be matched before i + for (int i = 1; i < m; i++) + { + // if current char is "(" it can not be matched, a valid + // match must be ended with ")". we just check s[i] == ')' + if (s[i] == ')') + { + // so there are 2 match situations: + // 1. s[i - 1] == '('. it can match current ')'. we also + // need to check before it if we had a valid pair. + if (s[i - 1] == '(') + { + if (i > 1) + dp[i] = dp[i - 2] + 2; + else + dp[i] = 2; + continue; + } + // 2. s[i - 1] == ')'. it means there maybe has valid pair + // before. we need to know how much pairs before i. we + // can read it from dp[i], then we can get char before + // valid pair. like situation 1, if char == '(' it can + // be matched. but we need to noticed, if there is no + // valid pair before, this ')' must be ignored. + int k = i - dp[i - 1] - 1; + if (k < 0) + continue; + + if (s[k] == '(') + { + // if k > 1, see if we can add a valid pair before k + if (k > 1) + dp[i] = dp[i - 1] + dp[k - 1] + 2; + else + dp[i] = dp[i - 1] + 2; + } + } + } + + for (int i = 0; i < m; i++) + result = max(dp[i], result); + + free(dp); + return result; +} \ No newline at end of file diff --git a/tests/test_32.cpp b/tests/test_32.cpp new file mode 100644 index 0000000..eab9538 --- /dev/null +++ b/tests/test_32.cpp @@ -0,0 +1,74 @@ +// This file is generated by mkfile.py +// Date: 2026-06-26 + +#include +#include + +#include +#include + +class LongestValidParenthesesTest : public ::testing::Test +{ + protected: + void AssertLongestValidParentheses(const std::string &input, int expected) + { + std::vector buffer(input.begin(), input.end()); + buffer.push_back('\0'); + + EXPECT_EQ(longestValidParentheses(buffer.data()), expected); + } +}; + +TEST_F(LongestValidParenthesesTest, Example1) +{ + AssertLongestValidParentheses("(()", 2); +} + +TEST_F(LongestValidParenthesesTest, Example2) +{ + AssertLongestValidParentheses(")()())", 4); +} + +TEST_F(LongestValidParenthesesTest, Example3) +{ + AssertLongestValidParentheses("", 0); +} + +TEST_F(LongestValidParenthesesTest, ReturnsZeroWhenThereIsNoValidPair) +{ + AssertLongestValidParentheses("(", 0); + AssertLongestValidParentheses(")", 0); + AssertLongestValidParentheses("((((", 0); + AssertLongestValidParentheses("))))", 0); + AssertLongestValidParentheses(")(", 0); +} + +TEST_F(LongestValidParenthesesTest, EntireStringIsValid) +{ + AssertLongestValidParentheses("()", 2); + AssertLongestValidParentheses("()()", 4); + AssertLongestValidParentheses("(())", 4); + AssertLongestValidParentheses("(()())", 6); +} + +TEST_F(LongestValidParenthesesTest, FindsValidSubstringAfterInvalidPrefix) +{ + AssertLongestValidParentheses(")()", 2); + AssertLongestValidParentheses("())(())", 4); + AssertLongestValidParentheses("())()()", 4); +} + +TEST_F(LongestValidParenthesesTest, FindsLongestContiguousSubstring) +{ + AssertLongestValidParentheses("()(()", 2); + AssertLongestValidParentheses("(()(((()", 2); + AssertLongestValidParentheses("(()())())", 8); + AssertLongestValidParentheses("()(())", 6); +} + +TEST_F(LongestValidParenthesesTest, HandlesMultipleSeparatedValidBlocks) +{ + AssertLongestValidParentheses("()(()())", 8); + AssertLongestValidParentheses("())(()())", 6); + AssertLongestValidParentheses("(()())())(()(()))", 8); +}