B3950 题解
Source & Knowledge
2024 年 3 月语言月赛,由洛谷网校入门计划/基础计划提供。
题目大意
现代 szm 语采用罗马字表示,其划分音节的规则如下:
- 规定元音是字符
a、e、i、o、u之一。 - 一般地,一个音节仅包含一个元音,并且以元音结尾。
- 特别地,当且仅当
n后第一个字符不是元音时,n单独作一个音节。 - 一个音节至多包含
3 个字符。
将字符串
如果存在一个正整数
在 szm 语中有一些习语,一种习语对应有一些固定的字符串。如果一个字符串「包含」且仅「包含」一种习语的一个固定子串,那么这个字符串是这种习语。
某种习语对应
题目分析
注意到,询问的 s.find() 即可。
但是,szm 语允许单个元音构成一个音节。如果出现例如子串为 a,而查找到的位置的音节为 za,那么此时就会产生错误的匹配,导致答案错误。
我们设询问的字符串为
为了缩短代码,可以编写如下函数,用于判断字符
bool vowel(char c) {
return c == 'a' || c == 'i' || c == 'u' || c == 'e' || c == 'o';
}
同样地,由于 szm 语允许 n 单独构成一个音节,因此我们还需要判断匹配到的子串的末尾位置 n。如果是,并且
如果 n 且 n,那么说明匹配成功,就给匹配数加一,然后跳出循环,匹配下一个子串。
在匹配完所有子串后,如果只有一个子串成功匹配,那么表明这个字符串是这种习语,输出 Yes, Commander,否则输出 No, Commander。
cin >> n >> q;
for (int i = 1; i <= n; ++i) cin >> a[i];
while (q--) {
cnt = 0;
cin >> s;
for (int i = 1; i <= n; ++i) {
pos = s.find(a[i]);
if (pos == s.npos) continue;
while (pos != s.npos) {
if ((vowel(s[pos]) && pos && !vowel(s[pos - 1])) || (!vowel(s[pos]) && pos && !vowel(s[pos - 1]) && s[pos - 1] != 'n')) {
pos = s.find(a[i], pos + 1);
continue;
} if ((s[pos + a[i].size() - 1] == 'n' && (pos + a[i].size() >= s.size() || (pos + a[i].size() < s.size() && !vowel(s[pos + a[i].size()])))) || s[pos + a[i].size() - 1] != 'n') {
++cnt;
break;
} pos = s.find(a[i], pos + 1);
}
} cout << (cnt == 1 ? "Yes, Commander\n" : "No, Commander\n");
}
完整代码
#include <iostream>
using namespace std;
const int N = 15;
int n, q, cnt, pos;
string a[N], s;
bool flag;
bool vowel(char c) {
return c == 'a' || c == 'i' || c == 'u' || c == 'e' || c == 'o';
}
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
cin >> n >> q;
for (int i = 1; i <= n; ++i) cin >> a[i];
while (q--) {
cnt = 0;
cin >> s;
for (int i = 1; i <= n; ++i) {
pos = s.find(a[i]);
if (pos == s.npos) continue;
while (pos != s.npos) {
if ((vowel(s[pos]) && pos && !vowel(s[pos - 1])) || (!vowel(s[pos]) && pos && !vowel(s[pos - 1]) && s[pos - 1] != 'n')) {
pos = s.find(a[i], pos + 1);
continue;
} if ((s[pos + a[i].size() - 1] == 'n' && (pos + a[i].size() >= s.size() || (pos + a[i].size() < s.size() && !vowel(s[pos + a[i].size()])))) || s[pos + a[i].size() - 1] != 'n') {
++cnt;
break;
} pos = s.find(a[i], pos + 1);
}
} cout << (cnt == 1 ? "Yes, Commander\n" : "No, Commander\n");
} return 0;
}