为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第一题-字符串前缀
在线评测链接: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); } });