forked from MaskRay/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathremove-invalid-parentheses.cc
106 lines (103 loc) · 3.38 KB
/
remove-invalid-parentheses.cc
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
104
105
106
// Remove Invalid Parentheses
class Solution {
unordered_set<string> res;
void f(const string &s, string ss, int k, int left, int right, int state) {
if (k == s.size()) {
if (! left && ! right && ! state)
res.insert(ss);
return;
}
if (s[k] == '(') {
if (left > 0)
f(s, ss, k+1, left-1, right, state);
f(s, ss+'(', k+1, left, right, state+1);
} else if (s[k] == ')') {
if (right > 0)
f(s, ss, k+1, left, right-1, state);
if (state > 0)
f(s, ss+')', k+1, left, right, state-1);
} else
f(s, ss+s[k], k+1, left, right, state);
}
public:
vector<string> removeInvalidParentheses(string s) {
int l = 0, r = 0;
for (auto c: s)
if (c == '(')
l++;
else if (c == ')')
l ? l-- : r++;
f(s, "", 0, l, r, 0);
return vector<string>(res.begin(), res.end());
}
};
/// O(|ans|). no superfluous enumeration
#define REP(i, n) for (int i = 0; i < (n); i++)
#define ROF(i, a, b) for (int i = (b); --i >= (a); )
class Solution {
vector<string> halves, res;
vector<int> milestones, milestones2;
int split;
// enumerate valid left part: s[0 , split)
// invariant: for close parentheses in s[0 , milestones[i]], at least `i+1` of them must be removed
void forward(const string &s, string ss, int k, int i, int removed, bool can) {
if (k == split) {
halves.push_back(ss);
return;
}
if (s[k] == ')') {
int ii = k == milestones[i] ? i+1 : i;
if (can && removed < milestones.size()) // prefixes of continuous close parentheses can be removed, other parts are disallowed
forward(s, ss, k+1, ii, removed+1, true);
if (k < milestones[i] || removed > i) // if k == milestones[i], comply with the invariant
forward(s, ss+s[k], k+1, ii, removed, false);
} else
forward(s, ss+s[k], k+1, i, removed, true);
}
// enumerate valid right part: s[split, n)
// for open parentheses in s[milestones2[i] , n), at least `i+1` of them must be removed
void backward(const string &s, string ss, int k, int i, int removed, bool can) {
if (k == split) {
reverse(ss.begin(), ss.end());
for (auto &x: halves)
res.push_back(x+ss);
return;
}
k--;
if (s[k] == '(') {
int ii = i < milestones2.size() && k == milestones2[i] ? i+1 : i;
if (can && removed < milestones2.size()) // suffixes of continuous open parentheses can be removed, other parts are disallowed
backward(s, ss, k, ii, removed+1, true);
if (i == milestones2.size() || k > milestones2[i] || removed > i) // if k == milestones2[i], comply with the invariant
backward(s, ss+s[k], k, ii, removed, false);
} else
backward(s, ss+s[k], k, i, removed, true);
}
public:
vector<string> removeInvalidParentheses(string s) {
int unmatched = 0;
REP(i, s.size())
if (s[i] == '(')
unmatched++;
else if (s[i] == ')') {
if (unmatched > 0)
unmatched--;
else
milestones.push_back(i);
}
split = milestones.empty() ? 0 : milestones.back()+1;
unmatched = 0;
ROF(i, split, s.size())
if (s[i] == ')')
unmatched++;
else if (s[i] == '(') {
if (unmatched > 0)
unmatched--;
else
milestones2.push_back(i);
}
forward(s, "", 0, 0, 0, true);
backward(s, "", s.size(), 0, 0, true);
return res;
}
};