#P4520. 第1题-数据匹配
-
1000ms
Tried: 33
Accepted: 12
Difficulty: 3
所属公司 :
华为
时间 :2025年12月3日-非AI方向(通软&嵌软&测试&算法&数据科学)
-
算法标签>字符串
第1题-数据匹配
解题思路
题意整理:
-
输入是一串用空格分隔的字符串(空格、换行只作为分隔符)。
-
第一个字符串为给定的目标串
S。 -
之后最多 100 个字符串为待匹配的随机串(可能重复)。
-
匹配规则:
- 一个随机串要想匹配成功,必须是
S的前缀,即随机串的每一位和S从第 1 个字符开始依次相同,且随机串长度不能超过S。 - 匹配长度越长,匹配度越高。
- 一个随机串要想匹配成功,必须是
-
输出所有匹配成功的串及其出现次数,按“匹配度从高到低”排序,即按长度从大到小排序;长度相同时可按字典序从小到大排(保证结果稳定、易实现)。
-
若没有任何匹配成功的串,则输出
null。
实现方法(适用于三种语言):
-
读入所有字符串,取第一个为目标串
S,其余放入数组。 -
遍历每个随机串
t:- 若
len(t) <= len(S)且S以t为前缀(前len(t)个字符完全相同),则认为匹配成功。 - 使用映射结构(哈希表 / 字典 /
map)统计每个匹配串出现的次数。
- 若
-
若映射为空,直接输出
null。 -
否则把所有键(不同的匹配串)取出放入数组,根据
- 首关键字:长度从大到小
- 次关键字:字典序从小到大 进行排序。
-
按排序后的顺序输出
字符串 次数,每个结果一行。
用到的核心算法/数据结构:
- 字符串前缀判断:
startswith/compare/ 手写循环。 - 哈希计数:
dict/HashMap/unordered_map。 - 自定义排序:按长度与字典序排序。
复杂度分析
设随机串个数为 n(≤ 100),目标串长度为 L,随机串平均长度为 L'(L' ≤ L)。
- 前缀匹配检查每个串最多比较
L个字符,时间复杂度为O(n * L)。 - 对不同匹配串排序,最多
n个,排序复杂度为O(n log n)。 - 综合时间复杂度:
O(n * L + n log n),在数据范围内非常充足。 - 需要一个哈希表存储统计结果,空间复杂度为
O(n * L)(所有匹配串总长度)。
代码实现
Python
# 功能函数:根据目标串和随机串列表,返回排序后的(字符串, 次数)列表
import sys
from collections import defaultdict
def solve(target, arr):
count = defaultdict(int) # 统计每个匹配字符串的出现次数
# 遍历每个随机串,判断是否为目标串前缀
for s in arr:
# 长度不能超过目标串,且必须从第一个字符开始完全相同
if len(s) <= len(target) and target.startswith(s):
count[s] += 1
if not count:
return [] # 没有匹配结果
# 将所有匹配串取出后排序:
# 1. 长度从大到小
# 2. 长度相同按字典序从小到大
keys = list(count.keys())
keys.sort(key=lambda x: (-len(x), x))
return [(k, count[k]) for k in keys]
def main():
# 读取所有输入,按空白字符分割为单词列表
data = sys.stdin.read().split()
if not data:
return
target = data[0] # 第一个是给定字符串
arr = data[1:] # 后面的是随机字符串序列
ans = solve(target, arr)
if not ans:
print("null")
else:
for s, c in ans:
# 每行输出:字符串 次数
print(s, c)
if __name__ == "__main__":
main()
Java
import java.util.*;
// 主类名必须为 Main
public class Main {
// 功能函数:根据目标串和随机串列表,返回排序后的结果列表
// 使用 List<String[]> 保存,每个元素为 {字符串, 次数字符串}
public static List<String[]> solve(String target, List<String> arr) {
Map<String, Integer> map = new HashMap<>(); // 统计每个匹配字符串的出现次数
// 遍历随机串,判断是否为前缀
for (String s : arr) {
if (s.length() <= target.length() && target.startsWith(s)) {
map.put(s, map.getOrDefault(s, 0) + 1);
}
}
List<String[]> res = new ArrayList<>();
if (map.isEmpty()) {
return res; // 返回空列表表示没有匹配结果
}
// 将所有 key 取出进行排序
List<String> keys = new ArrayList<>(map.keySet());
Collections.sort(keys, new Comparator<String>() {
@Override
public int compare(String a, String b) {
// 先按长度从大到小
if (a.length() != b.length()) {
return b.length() - a.length();
}
// 再按字典序从小到大
return a.compareTo(b);
}
});
for (String k : keys) {
res.add(new String[]{k, String.valueOf(map.get(k))});
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<String> all = new ArrayList<>();
// 读到 EOF 为止,空格和换行都作为分隔
while (sc.hasNext()) {
all.add(sc.next());
}
sc.close();
if (all.isEmpty()) {
return;
}
String target = all.get(0); // 给定字符串
List<String> arr = all.subList(1, all.size()); // 随机字符串列表
List<String[]> ans = solve(target, arr);
if (ans.isEmpty()) {
System.out.println("null");
} else {
for (String[] item : ans) {
// 每行输出:字符串 次数
System.out.println(item[0] + " " + item[1]);
}
}
}
}
C++
#include <bits/stdc++.h>
using namespace std;
// 功能函数:根据目标串和随机串列表,返回排序后的结果
vector<pair<string, int>> solve(const string &target, const vector<string> &arr) {
unordered_map<string, int> cnt; // 统计每个匹配字符串次数
// 遍历随机串,判断是否为目标串前缀
for (const string &s : arr) {
if (s.size() <= target.size()) {
bool ok = true;
// 手动比较前缀
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] != target[i]) {
ok = false;
break;
}
}
if (ok) {
cnt[s]++;
}
}
}
vector<pair<string, int>> res;
if (cnt.empty()) return res; // 没有匹配结果
// 将统计结果拷贝到 vector 中便于排序
for (auto &kv : cnt) {
res.push_back(kv);
}
// 自定义排序:
// 1. 长度从大到小
// 2. 长度相同按字典序从小到大
sort(res.begin(), res.end(), [](const pair<string, int> &a, const pair<string, int> &b) {
if (a.first.size() != b.first.size())
return a.first.size() > b.first.size();
return a.first < b.first;
});
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
vector<string> all;
string s;
// 读到 EOF 为止,空格和换行都作为分隔
while (cin >> s) {
all.push_back(s);
}
if (all.empty()) return 0;
string target = all[0]; // 给定字符串
vector<string> arr(all.begin() + 1, all.end()); // 随机字符串列表
vector<pair<string, int>> ans = solve(target, arr);
if (ans.empty()) {
cout << "null\n";
} else {
for (auto &p : ans) {
// 每行输出:字符串 次数
cout << p.first << " " << p.second << "\n";
}
}
return 0;
}
题目内容
已知有一串随机的字符串序列,需要找出与给定字符串匹配的字符串,并按照匹配度从大到小排序,匹配规则如下:
1.随机字符串长度范围内的内容和给定字符串完全相同,随机字符串 必须从第一个字符开始匹配
2.匹配长度越长匹配度越低
输入描述
输入为 1 个字符串序列,其中
第一个字符串为给定的字符串
后续字符串为随机的字符串序列,字符串序列的最大个数限制为 100 个
字符串序列中可能有重复字符串。
空格和换行符是无效字符,字符串之间用空格隔开,空格个数随机。
输出描述
输出为匹配的字符串以及出现的次数,用空格隔开,每个字符串结果独立占一行显示,按匹配度由大到小进行先后显示。
当没有匹配数据是输 null
样例1
输入
abcdef bcdef ae
输出
null
说明
bcdef 和 abcdef 第一个字符不同,不匹配
ae 和 abcdef 第 2 个字符不同,不匹配
因此没有一个和 abcdef 匹配的字符串,输出为 null
样例2
输入
abcdef a bcdef ae abc abcde abcdefgh
输出
abcde 1
abc 1
a 1
说明
给定字符串是 abcde
1.匹配度最高的是 abcde ,其次是 abc ,a ,他们各自只出现 1 次。
2.abcdefgh 长度超出 abcdef 并不匹配,bcdef 与 abcdef 第一个字符不同 并不匹配.