春招模拟赛第十三场|美团|2023.4.15
- Status
- Done
- Rule
- IOI
- Problem
- 4
- Start at
- 2023-4-28 19:00
- End at
- 2023-4-28 21:00
- Duration
- 2 hour(s)
- Host
- Partic.
- 23
You cannot submit for this problem because the contest is ended. You can click "Open in Problem Set" to view this problem in normal mode.
当 len(s)>len(t) ,s 中第 len(t)+1 到 len(s) 这些字符都必须删除。
接下来我们考虑 [1,min(len(s,len(t)))] 的部分。 因为删除只能删除最后一个,所以删除一个字符前,必须删除其后面的所有字符,但是其后面的字符中,可能存在字符和 t 中对应位置的字符相等。
所以最好的操作就是遇到不同的字符则修改。
时间复杂度:O(n)
这里推荐几道贪心题目
LeetCode上的贪心题,代码随想录总结的非常好了,见 贪心 - 代码随想录
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
char s[N], t[N];
int ns, nt;
int n;
void solve() {
scanf("%s%s", s + 1, t + 1);
ns = strlen(s + 1), nt = strlen(t + 1);
int ans = 0;
// 如果 s 的长度大于 t 的长度,那么从 s[nt + 1] 到 s[ns] 必然都要删除
if (ns > nt) ans += ns - nt, ns = nt;
// 如果 s[i] != t[i] ,既然删除(只能修改末字符)和修改的代价相同,不如全部修改
for (int i = 1; i <= ns; ++i)
if (s[i] != t[i]) ans += 1;
printf("%d\n", ans);
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; ++i) {
solve();
}
return 0;
}
T = int(input())
while T > 0:
s = input()
t = input()
ns = len(s)
nt = len(t)
ans = 0
# 如果 s 的长度大于 t 的长度,那么从 s[nt + 1] 到 s[ns] 必然都要删除
if ns > nt:
ans += ns - nt
ns = nt
for i in range(ns):
# 如果 s[i] != t[i] ,既然删除(只能修改末字符)和修改的代价相同,不如全部修改
if s[i] != t[i]:
ans += 1
print(ans)
T -= 1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0) {
String s = sc.next();
String t = sc.next();
int ans = 0;
// 如果 s 的长度大于 t 的长度,那么从 s[nt + 1] 到 s[ns] 必然都要删除
int ns = s.length(), nt = t.length();
if (ns > nt) {
ans += ns - nt;
ns = nt;
}
for (int i = 0; i < ns; ++i) {
// 如果 s[i] != t[i] ,既然删除(只能修改末字符)和修改的代价相同,不如全部修改
if (s.charAt(i) != t.charAt(i)) {
ans += 1;
}
}
System.out.println(ans);
}
}
}
package main
import (
"fmt"
)
const N = 50010
func solve(s, t string) {
ns, nt := len(s), len(t)
ans := 0
// 如果 s 的长度大于 t 的长度,那么从 s[nt + 1] 到 s[ns] 必然都要删除
if ns > nt {
ans += ns - nt
ns = nt
}
// 如果 s[i] != t[i] ,既然删除(只能修改末字符)和修改的代价相同,不如全部修改
for i := 0; i < ns; i++ {
if s[i] != t[i] {
ans += 1
}
}
fmt.Printf("%d\n", ans)
}
func main() {
var T int
fmt.Scan(&T)
for i := 0; i < T; i++ {
var s, t string
fmt.Scan(&s, &t)
solve(s, t)
}
}
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
input += data;
return;
});
process.stdin.on('end', () => {
const lines = input.trim().split('\n');
const N = 50010;
function solve(s, t) {
let ns = s.length;
let nt = t.length;
let ans = 0;
// 如果 s 的长度大于 t 的长度,那么从 s[nt + 1] 到 s[ns] 必然都要删除
if (ns > nt) {
ans += ns - nt;
ns = nt;
}
// 如果 s[i] != t[i] ,既然删除(只能修改末字符)和修改的代价相同,不如全部修改
for (let i = 0; i < ns; i++) {
if (s[i] !== t[i]) {
ans += 1;
}
}
console.log(ans);
}
const T = Number(lines[0]);
for (let i = 0; i < T; i++) {
s = lines[i * 2 + 1].trim()
t = lines[i * 2 + 2].trim()
solve(s, t);
}
});
小美是一名优秀的软件工程师,他的公司最近接到了一个新项目,需要在短时间内实现一个新的字符串匹配功能。
在这个项目中,有两个字符串 S 和 T,需要将字符串 S 变换成字符串 T 的一个前缀。这个任务非常重要,因为它将决定整个项目的成功与否。
为了完成这个任务,小美开始进行了大量的研究和分析。他发现,每次操作可以修改 S 的一个字符,也可以删除一个 S 末尾的字符,这样才能将 S 变换成 T 的前缀。
现在小美需要写一段程序,来输出最少需要操作的次数。
第一行一个正整数 t ,表示数据组数;
对于每一组数据输入两行仅包含小写字母的字符串 S 和 T 。
1≤S.length(),T.length()≤5×104 , 1≤t≤10
对于每一组数据,输出一个整数,表示最少需要操作的次数。
输入
2
aba
abb
abcd
efg
输出
1
4
样例解释
第一组数据,可以修改最后一个字母,使得 S=abb ,是 T 的一个前缀;
第二组数据,需要将 S 整个串删除,操作次数为 4 。