华为非AI方向笔试真题 7月15号【字符补全】

字符补全(C++/Py/Java/Js/Go)题解

华为笔试真题 7月15号 非AI方向第三题 300分题型

题目内容

给定一个目标字符串 TTT 和一个源字符串 SSS,请你找出需要在 SSS 中最少插入 多少个字符(可以在任意位置插入),才能使得 TTT 成为 SSS 的子序列。

注意:

  1. 子序列定义 :对于一个字符串 UUU,如果字符串 VVV 可以通过删除 UUU 中的一些字符(可以删除 000 个或多个,不改变剩余字符的相对顺序)得到,则称 VVV 是 UUU 的子序列。
  • 例如:在 "acbdacbdacbd" 中,"ababab"、"acacac"、"adadad"、"cdcdcd"、"abcdabcdabcd"等都是其子序列。
  • 子序列中的字符在原字符串中不需要连续出现,但必须保持原有的相对顺序。
  • 例如:"ababab" 是 "axbyaxbyaxby" 的子序列,因为 'aaa' 在 'bbb' 之前出现。
  1. 只能插入字符,不能删除或修改现有字符。
  2. 插入的字符必须是 TTT 中有的字符。
    约束条件:
  • 1≤∣S∣,∣T∣≤25001 \le |S|, |T| \le 25001≤∣S∣,∣T∣≤2500
  • SSS 和 TTT 只包含小写字母 ′a′'a'′a′~′z′'z'′z′

输入描述

第一行输入目标字符串 TTT

第二行输入源字符串 SSS

输出描述

输出最少需要插入的字符数量

样例1

输入

复制代码
abc
ac

输出

复制代码
1

说明

在 'ccc' 前面插入 'bbb',得到 "abcabcabc",所以需要插入 111 个字符。这是最典型的情况,展示了当目标字符串只比源字符串多一个字符时如何处理。

样例2

输入

复制代码
abc
xyz

输出

复制代码
3

说明

源字符串 SSS 中没有目标字符串 TTT 的任何字符,需要插入 "abcabcabc" 全部 333 个字符。这是边界情况,展示了当两个字符串完全不相交时如何处理。

样例3

输入

复制代码
aaab
ab

输出

复制代码
2

说明

源字符串 SSS 只有 "ababab",而目标字符串 TTT 有三个 'aaa' 和一个 'bbb'。可以匹配一个 'aaa' 和一个 'bbb',但还需要插入两个 'aaa'。这是特殊情况,展示了重复字符的处理。

题解

思路

思路:动态规划

  1. 本题其实可以直接转换为求S T的最长公共子序列,要插入的字母数量就为T.size() - 最大公共子序列长度
  2. 求最长子序列使用对应模板即可,定义dp[i][j]数组,表示T 前 i 个字符和 S 前 j 个字符*的最长公共子序列长度
  3. 状态转移
    • 字符相同T[i-1] == S[j-1], 对应执行dp[i][j] = dp[i - 1][j - 1] + 1;
    • 字符不相同时,执行dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
  4. 最终结果即为T.size() - dp[n][m], 总体时间复杂度为O(nm)

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    string t,s;
    cin >> t;
    cin >> s;
    int n = t.size();
    int m = s.size();
    // dp[i][]j T 前 i 个字符 和 S 前 j 个字符 的最长公共子序列长度。
    vector<vector<int>> dp(n+1,vector<int>(m+1,0));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (t[i - 1] == s[j - 1]) {
                dp[i][j] = dp[i-1][j-1] + 1;
            } else {
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    int ans = n - dp[n][m];
    cout << ans;
    return 0;
}

java

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String t = sc.next();
        String s = sc.next();

        int n = t.length();
        int m = s.length();

        // dp[i][j]:T 前 i 个字符 和 S 前 j 个字符 的最长公共子序列长度。
        int[][] dp = new int[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (t.charAt(i - 1) == s.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        int ans = n - dp[n][m];
        System.out.print(ans);
    }
}

python

python 复制代码
t = input()
s = input()

n = len(t)
m = len(s)

# dp[i][j]:T 前 i 个字符 和 S 前 j 个字符 的最长公共子序列长度。
dp = [[0] * (m + 1) for _ in range(n + 1)]

for i in range(1, n + 1):
    for j in range(1, m + 1):
        if t[i - 1] == s[j - 1]:
            dp[i][j] = dp[i - 1][j - 1] + 1
        else:
            dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

ans = n - dp[n][m]
print(ans)

javascript

js 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const input = [];

rl.on("line", (line) => {
    input.push(line);
});

rl.on("close", () => {
    const t = input[0];
    const s = input[1];

    const n = t.length;
    const m = s.length;

    // dp[i][j]:T 前 i 个字符 和 S 前 j 个字符 的最长公共子序列长度。
    const dp = Array.from({ length: n + 1 }, () => Array(m + 1).fill(0));

    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            if (t[i - 1] === s[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }

    const ans = n - dp[n][m];
    console.log(ans);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	in := bufio.NewReader(os.Stdin)

	var t, s string
	fmt.Fscan(in, &t)
	fmt.Fscan(in, &s)

	n := len(t)
	m := len(s)

	// dp[i][j]:T 前 i 个字符 和 S 前 j 个字符 的最长公共子序列长度。
	dp := make([][]int, n+1)
	for i := 0; i <= n; i++ {
		dp[i] = make([]int, m+1)
	}

	for i := 1; i <= n; i++ {
		for j := 1; j <= m; j++ {
			if t[i-1] == s[j-1] {
				dp[i][j] = dp[i-1][j-1] + 1
			} else {
				dp[i][j] = max(dp[i-1][j], dp[i][j-1])
			}
		}
	}

	ans := n - dp[n][m]
	fmt.Print(ans)
}
相关推荐
爱写代码的阿木2 小时前
基于鸿蒙OS开发附近社交游戏平台(二十三)-拉黑系统、屏蔽与全局过滤
游戏·华为·harmonyos
Zachery Pole2 小时前
CCF-CSP备战NO.7【队列】
算法
闪电悠米3 小时前
力扣hot100-48.旋转图像-转置翻转详解
算法·leetcode·职场和发展
满天星83035773 小时前
【算法】最长递增子序列(三种解法)
算法
qizayaoshuap4 小时前
# 颜色混合器 — HarmonyOS RGB调色板与Slider组件实战
华为·harmonyos
啦啦啦啦啦zzzz4 小时前
算法:贪心算法
c++·算法·leetcode·贪心算法
不言鹅喻5 小时前
HarmonyOS ArkTS 实战:实现一个校园体育场馆预约应用
pytorch·华为·harmonyos
网络工程小王5 小时前
【HCIE-AI】11.模型 昇腾迁移适配-精度调试-性能调优
人工智能·学习·华为·迁移学习·昇腾
●VON5 小时前
鸿蒙 PC Markdown 编辑器存储安全:AtomicFile 原子提交与故障注入
安全·华为·编辑器·harmonyos·鸿蒙
清泓y5 小时前
RAG 技术
算法·ai