[Algo Beat Contest 017 A] 串哈希
按 kirai、daishuki、shuki 的优先级检查子串并顺序模拟气压变化。
OJ: luogu
题目 ID: P17232
难度:入门
标签:字符串模拟
日期: 2026-08-11 07:37
形式化题目
给定一个初始整数和一个字符串序列。依次处理每个字符串时,根据它是否包含若干固定子串,按指定优先级改变当前整数。全部处理后,根据最终整数是否为正输出数值差或固定字符串。
思路
这题的核心是“规则优先级”,不是哈希。每个字符串只需要判断是否包含三个固定子串:kirai、daishuki、shuki。
判断顺序必须和题面优先级一致:
- 先判断
kirai。一旦出现,就忽略另外两条加分规则。 - 再判断
daishuki。因为daishuki自身包含shuki,所以它必须排在shuki前面。 - 最后判断
shuki。 - 都不包含时,气压减一。
遇到 kirai 时还要注意当前气压的符号:若当前气压非负,就把它设为 0;若已经为负,则保持不变。
处理完所有字符串后,设最终气压为 shuki。
代码
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-08-11 07:37
* update_at: 2026-08-11 11:03
*/
#include <bits/stdc++.h>
using namespace std;
int n;
long long s, now_value;
bool has_substr(const string &word, const string &pat) {
return word.find(pat) != string::npos;
}
bool has_substr2(const string &word, const string &pat) {
if (pat.size() > word.size()) return false;
// 手动枚举起点,再逐字符比较,等价于判断 pat 是否为 word 的连续子串。
for (int i = 0; i + (int)pat.size() <= (int)word.size(); i++) {
bool same = true;
for (int j = 0; j < (int)pat.size(); j++) {
if (word[i + j] != pat[j]) {
same = false;
break;
}
}
if (same) return true;
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> s;
now_value = s;
for (int i = 1; i <= n; i++) {
string word;
cin >> word;
// 题面规则有优先级:kirai 最高,daishuki 高于 shuki。
if (has_substr2(word, "kirai")) {
if (now_value >= 0) now_value = 0;
}
else if (has_substr2(word, "daishuki")) {
now_value += 2;
}
else if (has_substr2(word, "shuki")) {
now_value += 1;
}
else {
now_value -= 1;
}
}
if (now_value > 0) cout << now_value - s << '\n';
else cout << "shuki\n";
return 0;
}复杂度
设所有字符串长度总和为
除读入字符串外,只维护当前气压,空间复杂度为
总结
这题容易错在 daishuki 包含 shuki,以及 kirai 的优先级最高。只要严格按题面顺序模拟,每一步气压变化就和定义一致。