comments | difficulty | edit_url | rating | source | tags | |||
---|---|---|---|---|---|---|---|---|
true |
困难 |
2432 |
第 332 场周赛 Q4 |
|
给你两个字符串 s
和 t
。
你可以从字符串 t
中删除任意数目的字符。
如果没有从字符串 t
中删除字符,那么得分为 0
,否则:
- 令
left
为删除字符中的最小下标。 - 令
right
为删除字符中的最大下标。
字符串的得分为 right - left + 1
。
请你返回使 t
成为 s
子序列的最小得分。
一个字符串的 子序列 是从原字符串中删除一些字符后(也可以一个也不删除),剩余字符不改变顺序得到的字符串。(比方说 "ace"
是 "abcde"
的子序列,但是 "aec"
不是)。
示例 1:
输入:s = "abacaba", t = "bzaa" 输出:1 解释:这个例子中,我们删除下标 1 处的字符 "z" (下标从 0 开始)。 字符串 t 变为 "baa" ,它是字符串 "abacaba" 的子序列,得分为 1 - 1 + 1 = 1 。 1 是能得到的最小得分。
示例 2:
输入:s = "cde", t = "xyz" 输出:3 解释:这个例子中,我们将下标为 0, 1 和 2 处的字符 "x" ,"y" 和 "z" 删除(下标从 0 开始)。 字符串变成 "" ,它是字符串 "cde" 的子序列,得分为 2 - 0 + 1 = 3 。 3 是能得到的最小得分。
提示:
1 <= s.length, t.length <= 105
s
和t
都只包含小写英文字母。
根据题目我们知道,删除字符的下标范围是 [left, right]
,最优的做法一定是删除 [left, right]
范围内的所有字符。也就是说,我们要删除字符串
因此,我们可以先预处理得到数组
而删除字符的长度具备单调性,如果删除长度为
时间复杂度
class Solution:
def minimumScore(self, s: str, t: str) -> int:
def check(x):
for k in range(n):
i, j = k - 1, k + x
l = f[i] if i >= 0 else -1
r = g[j] if j < n else m + 1
if l < r:
return True
return False
m, n = len(s), len(t)
f = [inf] * n
g = [-1] * n
i, j = 0, 0
while i < m and j < n:
if s[i] == t[j]:
f[j] = i
j += 1
i += 1
i, j = m - 1, n - 1
while i >= 0 and j >= 0:
if s[i] == t[j]:
g[j] = i
j -= 1
i -= 1
return bisect_left(range(n + 1), True, key=check)
class Solution {
private int m;
private int n;
private int[] f;
private int[] g;
public int minimumScore(String s, String t) {
m = s.length();
n = t.length();
f = new int[n];
g = new int[n];
for (int i = 0; i < n; ++i) {
f[i] = 1 << 30;
g[i] = -1;
}
for (int i = 0, j = 0; i < m && j < n; ++i) {
if (s.charAt(i) == t.charAt(j)) {
f[j] = i;
++j;
}
}
for (int i = m - 1, j = n - 1; i >= 0 && j >= 0; --i) {
if (s.charAt(i) == t.charAt(j)) {
g[j] = i;
--j;
}
}
int l = 0, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
private boolean check(int len) {
for (int k = 0; k < n; ++k) {
int i = k - 1, j = k + len;
int l = i >= 0 ? f[i] : -1;
int r = j < n ? g[j] : m + 1;
if (l < r) {
return true;
}
}
return false;
}
}
class Solution {
public:
int minimumScore(string s, string t) {
int m = s.size(), n = t.size();
vector<int> f(n, 1e6);
vector<int> g(n, -1);
for (int i = 0, j = 0; i < m && j < n; ++i) {
if (s[i] == t[j]) {
f[j] = i;
++j;
}
}
for (int i = m - 1, j = n - 1; i >= 0 && j >= 0; --i) {
if (s[i] == t[j]) {
g[j] = i;
--j;
}
}
auto check = [&](int len) {
for (int k = 0; k < n; ++k) {
int i = k - 1, j = k + len;
int l = i >= 0 ? f[i] : -1;
int r = j < n ? g[j] : m + 1;
if (l < r) {
return true;
}
}
return false;
};
int l = 0, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
};
func minimumScore(s string, t string) int {
m, n := len(s), len(t)
f := make([]int, n)
g := make([]int, n)
for i := range f {
f[i] = 1 << 30
g[i] = -1
}
for i, j := 0, 0; i < m && j < n; i++ {
if s[i] == t[j] {
f[j] = i
j++
}
}
for i, j := m-1, n-1; i >= 0 && j >= 0; i-- {
if s[i] == t[j] {
g[j] = i
j--
}
}
return sort.Search(n+1, func(x int) bool {
for k := 0; k < n; k++ {
i, j := k-1, k+x
l, r := -1, m+1
if i >= 0 {
l = f[i]
}
if j < n {
r = g[j]
}
if l < r {
return true
}
}
return false
})
}