diff --git a/cpp/2210/221022.cpp b/cpp/2210/221022.cpp new file mode 100644 index 0000000..a137c8d --- /dev/null +++ b/cpp/2210/221022.cpp @@ -0,0 +1,84 @@ +#include +#include + +/** + * 76. Minimum Window Substring + * + * Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "". + * The testcases will be generated such that the answer is unique. + * A substring is a contiguous sequence of characters within the string. + */ + +class Solution { +private: + static inline int pos_of(char ch) { + return (ch > 'Z') ? (ch - 'a') : (ch - 'A' + 26); + } + +public: + static std::string minWindow(const std::string& s, const std::string& t) { + int m = s.length(), n = t.length(); + const char* sp = s.c_str(); + const char* tp = t.c_str(); + if (m < n) + return ""; + + int seg_tree[128]{}; + for (int i = 0; i < m; ++i) + ++seg_tree[pos_of(sp[i])]; + for (int i = 0; i < n; ++i) + ++seg_tree[64 + pos_of(tp[i])]; + for (int i = 0; i < 52; ++i) + if (seg_tree[i] < seg_tree[64 + i]) + return ""; + + // Initial build of seg tree + for (int i = 0; i < n; ++i) + --seg_tree[64 + pos_of(sp[i])]; + for (int i = 64; --i; ) + seg_tree[i] = std::max(seg_tree[i << 1], seg_tree[i << 1 | 1]); + if (seg_tree[1] <= 0) + return s.substr(0, n); + + // gradually expand & shrink + int L = 0, R = n, minL = 0x7FFFFFFF, mL, mR; // L inclusive, R exclusive + std::string ret; + while (R < m) { + // R+ + for (; R < m && seg_tree[1] > 0; ++R) { + int p = pos_of(sp[R]) + 64; + --seg_tree[p]; + // Update tree + while (p >>= 1) + seg_tree[p] = std::max(seg_tree[p << 1], seg_tree[p << 1 | 1]); + } + + // L+ + for (; L + n <= R; ++L) { + int p = pos_of(sp[L]) + 64; + if (seg_tree[p] >= 0) + break; + ++seg_tree[p]; + } + + // Update tree after L+ at once + for (int i = 64; --i; ) + seg_tree[i] = std::max(seg_tree[i << 1], seg_tree[i << 1 | 1]); + + if (seg_tree[1] <= 0 && minL > R - L && R - L > 0) + minL = (mR = R) - (mL = L); + + // Force update L + int p = pos_of(sp[L++]) + 64; + ++seg_tree[p]; + while (p >>= 1) + seg_tree[p] = std::max(seg_tree[p << 1], seg_tree[p << 1 | 1]); + } + return s.substr(mL, mR - mL); + } +}; + +int main() { + std::cout << Solution::minWindow("acbdbaab", "aabd") << "\n"; + return 0; +} diff --git a/cpp/2210/CMakeLists.txt b/cpp/2210/CMakeLists.txt index 45b05cf..2aa7491 100644 --- a/cpp/2210/CMakeLists.txt +++ b/cpp/2210/CMakeLists.txt @@ -3,4 +3,4 @@ PROJECT(2210) SET(CMAKE_CXX_STANDARD 23) -ADD_EXECUTABLE(2210 221022-CN.cpp) +ADD_EXECUTABLE(2210 221022.cpp)