题解:洛谷 P9940 Uddered but not Herd
【题目来源】
洛谷:P9940 [USACO21JAN] Uddered but not Herd B - 洛谷
【题目描述】
一个鲜为人知的事实是,奶牛拥有自己的文字:「牛文」。牛文由 \(26\) 个字母 a 到 z 组成,但是当奶牛说牛文时,可能与我们所熟悉的 abcdefghijklmnopqrstuvwxyz 不同,她会按某种特定的顺序排列字母。
为了打发时间,奶牛 Bessie 在反复哼唱牛文字母歌,而 Farmer John 好奇她唱了多少遍。
给定一个小写字母组成的字符串,为 Farmer John 听到 Bessie 唱的字母,计算 Bessie 至少唱了几遍完整的牛文字母歌,使得 Farmer John 能够听到给定的字符串。Farmer John 并不始终注意 Bessie 所唱的内容,所以他可能会漏听 Bessie 唱过的一些字母。给定的字符串仅包含他记得他所听到的字母。
【输入】
输入的第一行包含 \(26\) 个小写字母 a 到 z 的牛文字母表顺序。下一行包含一个小写字母组成的字符串,为 Farmer John 听到 Bessie 唱的字母。字符串的长度不小于 \(1\) 且不大于 \(1000\)。
【输出】
输出 Bessie 所唱的完整的牛文字母歌的最小次数。
【输入样例】
abcdefghijklmnopqrstuvwxyz
mood
【输出样例】
3
【核心思想】
-
问题分析:给定一个牛文字母表顺序(26个字母的排列),以及Bessie哼唱时Farmer John听到的部分字母序列(可能漏听)。求Bessie至少完整哼唱了多少遍字母歌,才能让John听到给定的序列。由于每遍字母歌都是从字母表第一个唱到最后一个,John听到的序列必须能按顺序划分为若干段,每段都是字母表的一个子序列(不要求连续,因为可以漏听)。因此问题转化为:给定一个参照顺序(字母表),一个目标序列,求最少需要多少个“递增段”才能覆盖该序列,其中每一段内的字符在参照顺序中严格递增。
-
算法选择:
- 贪心扫描:遍历目标字符串,如果当前字符在前一个字符之后出现(在字母表顺序中位置更大),则可以放在同一遍中;否则,必须开始新的一遍。计数器加1。
- 位置映射:用
pos[26]数组记录每个字母在牛文字母表中的位置(0~25),以O(1)时间比较顺序。
-
关键步骤:
- 预处理:读入字母表顺序字符串
alpha(长度26)和目标字符串s。 - 建立位置映射:遍历
alpha,令pos[alpha[i] - 'a'] = i,记录每个字母在字母表中的排名。 - 初始化:答案
ans = 1(至少需要唱一遍才能听到第一个字母)。 - 扫描目标字符串:从
i = 1到len(s)-1:- 若
pos[s[i]] <= pos[s[i-1]],说明当前字母在字母表中的位置不晚于前一个字母,无法在同一遍中按顺序唱到(因为同一遍中字母顺序必须严格递增),因此需要额外再唱一遍,ans++。 - 否则,说明可以接在上一遍的同一遍中,不需要增加遍数。
- 若
- 输出
ans。
- 预处理:读入字母表顺序字符串
-
时间/空间复杂度:
- 时间复杂度:\(O(26 + |s|)\),主要开销在扫描目标字符串。
- 空间复杂度:\(O(26)\),用于存储位置映射。
-
贪心模拟的核心思想:
- 分段本质:目标序列中,凡是在字母表顺序上出现“下降”或“持平”的位置,都必然被划分到不同的完整哼唱遍数中。因为每遍字母歌内字母顺序严格按字母表递增。
- 只关心相邻字符:由于遍数划分只需满足每段内递增,那么只需检查相邻两个被听到的字符是否递增。如果递增,它们可归为同一遍;否则,必须开启新的一遍。这种贪心策略得到的遍数是最小的。
- 适用场景:适用于判断一个序列能分解为多少个给定有序集合的子序列的问题,核心是比较相邻元素在参照顺序中的相对位置。
【算法标签】
入门 #模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
string s1, s2;
int ans=1;
int main()
{
cin >> s1 >> s2; // 输入字符串s1和s2
for (int i=1; i<s2.length(); i++) { // 遍历s2字符串
if (s1.find(s2[i])<=s1.find(s2[i-1])) ans++; // 查找s2[i]与s2[i-1]在s1中的先后位置,如果小于等于,则说明一遍中无法唱到,需要再唱一遍
}
cout << ans << endl; // 最后打印结果
return 0;
}
【运行结果】
abcdefghijklmnopqrstuvwxyz
mood
3
浙公网安备 33010602011771号