[蓝桥杯][2019年第十届真题]人物相关性分析
题目描述
小明正在分析一本小说中的人物相关性。他想知道在小说中 Alice 和 Bob 有多少次同时出现。
更准确的说,小明定义 Alice 和 Bob“同时出现”的意思是:在小说文本 中 Alice 和 Bob 之间不超过 K 个字符。
例如以下文本:
This is a story about Alice and Bob. Alice wants to send a private message to Bob. 假设 K = 20,则 Alice 和 Bob 同时出现了 2 次,分别是”Alice and Bob”
和”Bob. Alice”。前者 Alice 和 Bob 之间有 5 个字符,后者有 2 个字符。 注意:
- Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。
- Alice 和 Bob 应为单独的单词,前后可以有标点符号和空格,但是不能
有字母。例如 Bobbi 并不算出现了 Bob。
输入
第一行包含一个整数 K。 第二行包含一行字符串,只包含大小写字母、标点符号和空格。长度不超
过 1000000。
输出
输出一个整数,表示 Alice 和 Bob 同时出现的次数
样例
样例输入
20
This is a story about Alice and Bob. Alice wants to send a private message to Bob.
样例输出
2
思路:
在字符串中找出 Alice 和 Bob 所有位置的起点和终点,然后二分查找即可。
代码:
int main() {
int k; cin >> k;
getchar();
string s; getline(cin, s);
int len_s = s.size();
vector<int> alice_l, alice_r, bob_l, bob_r;
for (int i = 0; i < len_s; i ++) {
// 判断 Alice
if (i + 4 < len_s) {
string Alice = "";
for (int j = i; j <= i + 4; j ++) Alice += s[j];
if (Alice == "Alice") {
// 判断是否是独立的单词
char a = '.', b = '.';
if (i > 0) a = s[i - 1];
if (i + 5 < len_s) b = s[i + 5];
if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'));
else if ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'));
else {
alice_l.pb(i);
alice_r.pb(i + 4);
}
}
}
// 判断 Bob
if (i + 2 < len_s) {
string Bob = "";
for (int j = i; j <= i + 2; j ++) Bob += s[j];
if (Bob == "Bob") {
// 判断是否是独立的单词
char a = '.', b = '.';
if (i > 0) a = s[i - 1];
if (i + 3 < len_s) b = s[i + 3];
if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'));
else if ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'));
else {
bob_l.pb(i);
bob_r.pb(i + 2);
}
}
}
}
ll ans = 0;
// 查找 Alice 的 A 左边的 Bob
for (int i = 0; i < alice_l.size(); i ++) {
int x = alice_l[i];
int y = x - k - 1;
int l = lower_bound(all(bob_r), y) - bob_r.begin();
int r = lower_bound(all(bob_r), x) - bob_r.begin() - 1;
if (r >= l) ans += r - l + 1;
}
// 查找 Alice 的 e 右边的 Bob
for (int i = 0; i < alice_r.size(); i ++) {
int x = alice_r[i];
int y = k + x + 1;
int l = lower_bound(all(bob_l), x) - bob_l.begin();
int r = lower_bound(all(bob_l), y + 1) - bob_l.begin() - 1;
if (r >= l) ans += r - l + 1;
}
cout << ans << endl;
return 0;
}