主要思想是滑动窗口
用两个数组记录Alice和Bob出现时(首字母)的下标
遍历Alice数组中的元素,在Bob数组中维护范围内的窗口
范围为:Alice[i] - k - 3 <= Bob[ ] <= Alice[i] + k + 5 (3 和 5 分别为Bob和Alice的长度)
每次循环让答案加上窗口长度即可( r 表示的是窗口右边界后一位,是为方便计算,不用加一)
#include<bits/stdc++.h>
using namespace std;
int k;
string str;
const int N = 200000;
int Alice[N], Bob[N];
int main()
{
cin >> k;
getchar();
getline(cin, str);
int n = str.size();
int a = 0, b = 0;
int cur = 0;
while(cur < n)
{
int pos = str.find("Alice", cur);
if(pos == -1) break;
if((pos + 5 >= n || !isalpha(str[pos + 5])) && (pos - 1 < 0 || !isalpha(str[pos - 1]))) Alice[a ++] = pos;
cur = pos + 5;
}
cur = 0;
while(cur < n)
{
int pos = str.find("Bob", cur);
if(pos == -1) break;
if((pos + 3 >= n || !isalpha(str[pos + 3])) && (pos - 1 < 0 || !isalpha(str[pos - 1]))) Bob[b ++] = pos;
cur = pos + 3;
}
long long ans = 0;
for(int i = 0, l = 0, r = 0; i < a; i ++)
{
while(l < b && Bob[l] < Alice[i] - 3 - k) l ++;
while(r < b && Bob[r] <= Alice[i] + 5 + k) r ++;
//cout << l << ' ' << r << endl;
ans += r - l;//
}
cout << ans;
}