题目描述:
小明正在分析一本小说中的人物相关性。他想知道在小说中 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。
(对于所有评测用例,1≤ K ≤1000000。)
输出:
输出一个整数,表示 Alice 和 Bob 同时出现的次数
样例输入:
20
This is a story about Alice and Bob. Alice wants to send a private message to Bob.
样例输出:
2
分析:
我们可以用两个vector< int >来存放Alice,Bob的下标
#include <bits/stdc++.h>
using namespace std;
string s; //定义全局变量s
bool checkA(int i, int len){ //判断是否为Alice, i为下标, len为字符串长度
if(len - i < 5) return false;
return s[i+1] == 'l' && s[i+2] == 'i' && s[i+3] == 'c' && s[i+4] == 'e';
}
bool checkB(int i, int len){ //判断是否为Bob, i为下标, len为字符串长度
if(len - i < 3) return false;
return s[i+1] == 'o' && s[i+2] == 'b';
}
int main(){
int k; //定义k
cin >> k; //输入k
getchar(); //吃回车
getline(cin, s); //整行输入字符串s
int len = s.length(); //定义len为s的长度
vector<int> Alice, Bob; //定义数组记录名字出现时的下标
for(int i = 0; i < len; i++){ //遍历字符串
if(s[i] == 'A' && checkA(i, len)){ //如果字符为'A'判断是否为Alice
Alice.push_back(i); //添加下标到数组
i += 5; //跳过名字(名字后后空格,无需担心循环中的i++)
}
else if(s[i] == 'B' && checkB(i, len)){ //如果字符为'B'判断是否为Bob
Bob.push_back(i); //添加下标到数组
i += 3; //跳过名字
}
}
int As = Alice.size(), Bs = Bob.size(); //As与Bs分别为两数组元素个数
int bl = 0, br = 0; //bl与br分别为窗口左右边界
long long ans = 0; //定义答案(最后一个评测点会超过int范围)
for(int i = 0; i < As; i++){ //遍历Alice数组元素
while(bl < Bs && Bob[bl] < Alice[i] - k - 3) bl++; //维护窗口左边界
while(br < Bs && Bob[br] <= Alice[i] + k + 5) br++; //维护窗口右边界
ans += br - bl; //答案加上窗口中元素个数
}
cout << ans << endl; //输出答案
return 0;
}