单词与文章统一转小写,逐位检查匹配并判断左右是否为单词边界。
OJ: roj
题目 ID: 3585
难度:普及-
标签:输入输出字符串python
创建: 2026-10-02 09:15
更新: 2026-10-06 14:33
题目描述
给定一个只含字母的单词和一篇只含字母与空格的文章,输出该单词在文章中出现次数及首次出现位置(首字母下标从
数据范围:单词长度
思路
先把单词和文章统一转成小写,再枚举文章中的每个起始位置,检查该位置起连续
参考代码
Python 版:
python
#!/usr/bin/env python3
# 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-10-02 09:15
# update_at: 2026-10-02 09:15
import re
import sys
from collections.abc import Iterator
def find_hits(article: str, word: str) -> Iterator[int]:
"""产出 word 作为独立单词在 article 中每次匹配的起始下标(不区分大小写)。
文章只含字母和空格,所以单词边界等价于"前后不是小写字母";
两侧的环视让整串匹配只需一次线性扫描,不产生重叠假匹配。
"""
pattern = re.compile(rf'(?<![a-z]){re.escape(word)}(?![a-z])')
return (m.start() for m in pattern.finditer(article))
def solve() -> None:
data = iter(sys.stdin.read().splitlines()) # 文章里的空格是单词边界,必须按行保留
word = next(data).strip().lower()
article = next(data).lower()
hits = list(find_hits(article, word))
if hits:
print(len(hits), hits[0]) # 出现次数 + 首次位置(首字母下标,从 0 计)
else:
print(-1)
if __name__ == "__main__":
solve()C++ 版(同一算法):
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-10-06 14:33
* update_at: 2026-10-06 14:33
*/
#include <iostream>
#include <string>
using namespace std;
typedef long long ll;
string word, article;
// 把 c 转成小写
inline char lower(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A' + 'a';
return c;
}
// 判断 c 是否为字母
inline bool is_alpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
getline(cin, word);
getline(cin, article);
// 统一转小写
for (size_t i = 0; i < word.size(); ++i) word[i] = lower(word[i]);
for (size_t i = 0; i < article.size(); ++i) article[i] = lower(article[i]);
ll m = word.size();
ll n = article.size();
ll cnt = 0;
ll first = -1;
// 在 article 中逐位检查是否匹配 word 且左右为单词边界
for (ll i = 0; i + m <= n; ++i) {
// 检查 article[i..i+m-1] 是否等于 word
bool match = true;
for (ll j = 0; j < m; ++j) {
if (article[i + j] != word[j]) {
match = false;
break;
}
}
if (!match) continue;
// 左边界:i == 0 或 article[i-1] 不是字母
if (i > 0 && is_alpha(article[i - 1])) continue;
// 右边界:i + m == n 或 article[i+m] 不是字母
if (i + m < n && is_alpha(article[i + m])) continue;
++cnt;
if (first == -1) first = i;
}
if (cnt == 0) {
cout << -1 << '\n';
} else {
cout << cnt << ' ' << first << '\n';
}
return 0;
}