题意
解题思路
- 先求出字符串中所有Alice的下标和Bob的下标,把前者的下标存到a数组中,后者存到b数组中。很显然,a数组和b数组都是非严格递增的。因为是java嘛,所以用List来代替数组。
- 遍历a数组,a数组的每个元素都代表一个Alice的下标,不妨把这个值称之为ax。那么对于这个alice,有哪些Bob是和它相邻的呢?很显然,是下标位于[ax - k - 3, ax + k + 5]之间的Bob。所以我们二分搜索一下b数组,获取b数组中处于[ax - k - 3, ax + k + 5]区间的值的个数,然后加到答案里就可以了。
- 最后的最后,答案的数值是有可能爆int的,所以要开long。太坑了,尤其是对于蓝桥杯这种不能实时测评并反馈的比赛。
ps:对于该题,蓝桥杯官方OJ的测试数据是错的,想测评代码请选择其他OJ,比如acwing等等。
代码
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;
public class Main{
static int k;
static Scanner sc = new Scanner(System.in);
static String s;
// 从左到右,返回第一个大于等于x的数的下标,如果没有则返回-1
static int lowerBound(int x, List<Integer> list) {
if(list.get(list.size() - 1) < x) {
return -1;
}
// 二分
int l = 0, r = list.size() - 1;
while(l < r) {
int mid = (l + r) / 2;
if(list.get(mid) >= x) {
r = mid;
}
else {
l = mid + 1;
}
}
return l;
}
// 从右往左,返回第一个小于等于x的数的下标,如果没有返回-1
static int findLastLower(int x, List<Integer> list) {
if(list.get(list.size() - 1) <= x) {
return list.size() - 1;
}
// 二分找到从左往右第一个大于x的数的下标
int l = 0, r = list.size() - 1;
while(l < r) {
int mid = (l + r) / 2;
if(list.get(mid) > x) {
r = mid;
}
else {
l = mid + 1;
}
}
// l - 1就是从右往左第一个小于等于x的数的下标,当l等于0时,说明不存在,返回l - 1 即 -1
return l - 1;
}
static boolean check(int i) {
if(i < 0 || i >= s.length()) {
return true;
}
if(s.charAt(i) <= 'z' && s.charAt(i) >= 'a') {
return false;
}
if(s.charAt(i) <= 'Z' && s.charAt(i) >= 'A') {
return false;
}
return true;
}
public static void main(String[] args) {
k = sc.nextInt();
s = sc.nextLine();
s = sc.nextLine();
long ans = 0;
// a存放所有Alice的下标, b存放所有Bob的下标
List<Integer> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
// 遍历字符串,填充a和b
for(int i = 0; i < s.length(); i++) {
if(i + 3 <= s.length() &&s.substring(i, i + 3).equals("Bob") && check(i + 3) && check(i - 1)) {
b.add(i);
}
if(i + 5 <= s.length() && s.substring(i, i + 5).equals("Alice") && check(i + 5) && check(i - 1)) {
a.add(i);
}
}
for(int ax : a) {
// ax为Alice下标,找到下标在[ax - k - 3, ax + k + 5]区间的bob个数,然后加到ans里面
int l = lowerBound(ax - k - 3, b);
int r = findLastLower(ax + k + 5, b);
if(l == -1 || r == -1) {
continue;
}
ans += r - l + 1;
}
System.out.println(ans);
}
}