L1-101 别再来这么多猫娘了(分数20) 字符串处理
题目描述
给出若干个违禁词和阈值,再给出需要审查的句子,将其中的违禁词替换成
就输出“He Xie Ni Quan Jia!”。
输入示例:
第一行给出一个正整数n,表示违禁词的个数,接下来n行,每行给出一个违禁词。
每行一个长度不超过 10 的、只包含大小写字母、数字及 ASCII 码范围内的标点符号的单词
再给出一个非负整数k,表示阈值,下一行输入要审查的句子。
题解
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
if (!(cin >> n)) return 0;
vector<string> bad_words(n);
for (int i = 0; i < n; i++) cin >> bad_words[i];
int k;
cin >> k;
string dummy;
getline(cin, dummy); // 吃掉换行符
string text;
getline(cin, text);
string temp = text; // 复制一份副本,用来随意修改
int count = 0;
// jump[i] = len 表示:在位置 i,有一个长度为 len 的违禁词
vector<int> jump(text.size(), 0);
// 按输入顺序(优先级)遍历
for (const string& word : bad_words)
{
size_t pos = 0;
int len = word.length();
// 在副本 temp 里查找
while ((pos = temp.find(word, pos)) != string::npos)
{
count++;
// 1. 记录一下这里被和谐了,长度是 len
jump[pos] = len;
/*
2. 【最关键一步】把副本里的这个词变成等长的 '*'
这样长度没变,但内容变了,后面的词就不可能匹配到这里了
这里替换成*的原因是find的查找功能特别花心,与专一的regex不同,只要出现了违禁词,不管是独立的还是嵌在某个字符串里的,都
会被找到,这就导致答案会出错(本题良心地扣了2分😄)
*/
temp.replace(pos, len, string(len, '*'));
// 3. 继续往后找
pos += len;
}
}
// --- 输出部分 ---
if (count >= k)
{
cout << count << endl;
cout << "He Xie Ni Quan Jia!" << endl;
}
else
{
for (int i = 0; i < text.size(); )
{
if (jump[i] > 0)
{
// 这里有记录,说明是违禁词
cout << "<censored>";
// 这一步直接跳过原词的长度
i += jump[i];
}
else
{
// 没记录,输出原字符
cout << text[i];
i++;
}
}
cout << endl;
}
return 0;
}

浙公网安备 33010602011771号