为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第一题-字符串前缀
在线评测链接:P1235
题目内容
塔子哥是一名优秀的软件工程师,他的公司最近接到了一个新项目,需要在短时间内实现一个新的字符串匹配功能。
在这个项目中,有两个字符串 S 和 T,需要将字符串 S 变换成字符串 T 的一个前缀。这个任务非常重要,因为它将决定整个项目的成功与否。
为了完成这个任务,塔子哥开始进行了大量的研究和分析。他发现,每次操作可以修改 S 的一个字符,也可以删除一个 S 末尾的字符,这样才能将 S 变换成 T 的前缀。
现在塔子哥需要写一段程序,来输出最少需要操作的次数。
输入描述
第一行一个正整数 t ,表示数据组数;
对于每一组数据输入两行仅包含小写字母的字符串 S 和 T 。
,
,
输出描述
对于每一组数据,输出一个整数,表示最少需要操作的次数。
样例
输入
2 aba abb abcd efg
输出
1 4
样例解释
第一组数据,可以修改最后一个字母,使得 S=abb ,是 T 的一个前缀;
第二组数据,需要将 S 整个串删除,操作次数为 4 。
思路
思维 + 贪心
当 len(s) > len(t) ,s 中第 len(t) + 1 到 len(s) 这些字符都必须删除。
接下来我们考虑 [1, min(len(s, len(t)))] 的部分。 因为删除只能删除最后一个,所以删除一个字符前,必须删除其后面的所有字符,但是其后面的字符中,可能存在字符和 t 中对应位置的字符相等。
所以最好的操作就是遇到不同的字符则修改。
时间复杂度:O(n)
类似题目推荐
这里推荐几道贪心题目
Leetcode
LeetCode上的贪心题,代码随想录总结的非常好了,见 贪心 - 代码随想录
Codefun2000
-
P1091. 米哈游 2023.03.19-第一题-交换字符
-
P1235. 百度 2023.04.15-实习-第一题-字符串前缀
-
P1005. 腾讯 2022.10.16-汽车
-
P1137 美团 2023.04.01-第一题-整理
-
P1077 美团 2023.3.11-第一题-字符串修改
-
P1024 百度 2022.9.13-01反转
-
P1089 美团 2023.3.18.10点-第三题-塔子哥的回文串
代码
CPP
#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;
}
python
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
Java
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);
}
}
}
Go
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)
}
}
Js
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);
}
});


















