class Solution:
def minLength(self, s: str) -> int:
res = []
for c in s:
if c == 'B':
if res and res[-1] == 'A':
res.pop()
else:
res.append(c)
elif c == 'D':
if res and res[-1] == 'C':
res.pop()
else:
res.append(c)
else:
res.append(c)
return len(res)

class Solution:
def minLength(self, s: str) -> int:
stack = []
for c in s:
stack.append(c)
if len(stack) >= 2 and ((stack[-2] == 'A' and stack[-1] == 'B') or (stack[-2] == 'C' and stack[-1] == 'D')):
stack.pop()
stack.pop()
return len(stack)
方法: 栈 O(n)
class Solution:
def minLength(self, s: str) -> int:
stack = []
for c in s:
if stack and ((stack[-1] == 'A' and c == 'B') or (stack[-1] == 'C' and c == 'D')):
stack.pop()
else:
stack.append(c)
return len(stack)
C++
class Solution {
public:
int minLength(string s) {
stack<char> st;
for (char c : s){
if (!st.empty() && ((st.top() == 'A' && c == 'B') || st.top() == 'C' && c == 'D')){
st.pop();
}
else{
st.push(c);
}
}
return st.size();
}
};
Python3
方法一: 动态规划
动态规划 ⟮O(n)、O(n)⟯
class Solution:
def addMinimum(self, word: str) -> int:
n = len(word)
d = [0] * (n+1)
for i in range(1, n+1):
d[i] = d[i-1] + 2
if i > 1 and word[i-1] > word[i-2]:
d[i] = d[i-1] - 1
return d[n]
动态规划 ⟮O(n)、O(1)⟯
class Solution:
def addMinimum(self, word: str) -> int:
n = len(word)
pre = 0
for i in range(1, n+1):
cur = pre + 2
if i > 1 and word[i-1] > word[i-2]:
cur = pre - 1
pre = cur
return pre

方法二: 直接拼接 ⟮O(n)、O(1)⟯

class Solution:
def addMinimum(self, word: str) -> int:
n = len(word)
res = ord(word[0]) - ord(word[n-1]) + 2
for i in range(1, n):
res += (ord(word[i]) - ord(word[i-1]) + 2) % 3
return res

方法三: 计算组数 ⟮O(n)、O(1)⟯


class Solution:
def addMinimum(self, word: str) -> int:
n = len(word)
cnt = 0
for i in range(1, n):
if word[i] <= word[i-1]:
cnt += 1
return 3 * (cnt + 1) - n
class Solution:
def addMinimum(self, word: str) -> int:
n = len(word)
cnt = 1
for i in range(1, n):
if word[i] <= word[i-1]:
cnt += 1
return 3 * cnt - n

C++
方法一: 动态规划
动态规划 ⟮O(n)、O(n)⟯
class Solution {
public:
int addMinimum(string word) {
int n = word.size();
vector<int> d(n+1);
for (int i = 1; i <= n; ++i){
d[i] = d[i-1] + 2;
if (i > 1 && word[i-1] > word[i-2]){
d[i] = d[i-1] - 1;
}
}
return d[n];
}
};
动态规划 ⟮O(n)、O(1)⟯
class Solution {
public:
int addMinimum(string word) {
int n = word.size();
int pre = 0;
int cur = 0;
for (int i = 1; i <= n; ++i){
cur = pre + 2;
if (i > 1 && word[i-1] > word[i-2]){
cur = pre - 1;
}
pre = cur;
}
return pre;
}
};
方法二: 直接拼接 ⟮O(n)、O(1)⟯
class Solution {
public:
int addMinimum(string word) {
int n = word.size();
int res = word[0] - word[n-1] + 2;
for (int i = 1; i < n; ++i){
res += (word[i] - word[i-1] + 2) % 3;
}
return res;
}
};
方法三: 计算组数 ⟮O(n)、O(1)⟯
class Solution {
public:
int addMinimum(string word) {
int n = word.size();
int cnt = 1;
for (int i = 1; i < n; ++i){
if (word[i] <= word[i-1]){
cnt += 1;
}
}
return 3 * cnt - n;
}
};
Python3
方法一: 动态规划⟮O(L+n3)、O(L+n)⟯
class Solution:
def minExtraChar(self, s: str, dictionary: List[str]) -> int:
n = len(s)
f = [0] * (n+1)
d = set(dictionary)
for i in range(n):
f[i+1] = f[i] + 1
for j in range(i+1):
if s[j:i+1] in d:
f[i+1] = min(f[i+1], f[j])
return f[n]

方法二:字典树优化 ⟮O(max_l∗L+n2)、O(max_l∗L∗C+n)⟯
class Trie:
def __init__(self):
self.children = [None for _ in range(26)]
self.isEnd = False
def insert(self, word):
node = self
for ch in word:
k = ord(ch) - ord('a')
if node.children[k] == None:
node.children[k] = Trie()
node = node.children[k]
node.isEnd = True
def track(self, node, ch):
k = ord(ch) - ord('a')
if node == None or node.children[k] == None:
return None, False
node = node.children[k]
return node, node.isEnd
class Solution:
def minExtraChar(self, s: str, dictionary: List[str]) -> int:
n = len(s)
f = [0] * (n+1)
trie = Trie()
for e in dictionary:
trie.insert(reversed(e))
for i in range(n):
f[i+1] = f[i] + 1
node = trie
for j in range(i, -1, -1):
node, ok = trie.track(node, s[j])
if ok:
f[i+1] = min(f[i+1], f[j])
return f[n]
C++
方法一: 动态规划⟮O(L+n3)、O(L+n)⟯
class Solution {
public:
int minExtraChar(string s, vector<string>& dictionary) {
unordered_set<string> set(dictionary.begin(), dictionary.end());
int n = s.size();
vector<int> f(n+1);
for (int i = 0; i < n; ++i){
f[i+1] = f[i] + 1;
for (int j = 0; j <= i; ++j){
if (set.count(s.substr(j, i-j+1))){
f[i+1] = min(f[i+1], f[j]);
}
}
}
return f[n];
}
};
方法二:字典树优化 ⟮O(max_l∗L+n2)、O(max_l∗L∗C+n)⟯
class Trie{
private:
vector<Trie*> children;
bool isEnd;
public:
Trie():children(26), isEnd(false){}
void insert(string word){
Trie* node = this;
for (char ch : word){
ch -= 'a';
if (node->children[ch] == nullptr){
node->children[ch] = new Trie();
}
node = node -> children[ch];
}
node->isEnd = true;
}
bool track(Trie*& node, char ch){
if (node == nullptr || node->children[ch - 'a'] == nullptr){
node = nullptr;
return false;
}
node = node->children[ch - 'a'];
return node->isEnd;
}
};
class Solution {
public:
int minExtraChar(string s, vector<string>& dictionary) {
int n = s.size();
vector<int> f(n+1, 0);
Trie trie;
for (auto s : dictionary){
reverse(s.begin(), s.end());
trie.insert(s);
}
for (int i = 0; i < n; ++i){
f[i+1] = f[i] + 1;
Trie* node = ≜
for (int j = i; j >= 0; --j){
if (trie.track(node, s[j])){
f[i+1] = min(f[i+1], f[j]);
}
}
}
return f[n];
}
};