题目及分析
问题描述】
小明正在分析一本小说中的人物相关性。他想知道在小说中 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 个字符。
注意:
1.Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。
2.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
【评测用例规模与约定】
对于所有评测用例,1≤ K ≤1000000。
分析题意:
- 注意输入格式,对scanner要做到换行输入
- 长度不超过100000,说明暴力枚举会超时
- 涉及判断前后均不为字母方法,以及字符串的截取操作
- 滑动窗口优化
源代码
package com.qustion;
import java.util.Scanner;
public class q6 {
static long result =0;
static int K;
static String text;
static int length;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
K=scanner.nextInt();
scanner.nextLine();
text=scanner.nextLine();
length=text.length();
//保存Alice和Bob的位置
int[]number1=new int[1000000];//数量要足够大
int[]number2=new int[1000000];
int count1=0;
int count2=0;
scanner.close();
for (int x = 0; x < length; x++) {
//判断并记录下二者的位置并保存在number1中,保证前后都不是字母
if(!isletter(x-1)&&x+4<length&&!isletter(x+5)&& text.substring(x,x+5).equals("Alice")){
number1[count1++]=x;
}
if (!isletter(x-1)&&x+2<length&&!isletter(x+3)&&text.substring(x,x+3).equals("Bob")){
number2[count2++]=x;//在number2中记下Bob的位置
}
}
if(count1==0||count2==0){
result=0;
}else {
int right=0,left=0;
for (int x=0;x<count1;x++){//滑动数组开始滑动
while (number2[left]<number1[x]-3-K){//left不存在于左边时需移位,且小于则循环继续
left++;
}
while (number2[right+1]<=number1[x]+K+5){//right+1存在于右边时移位,相当于加一
right++;
}
if(right-left>=0)result+=right-left+1;
/*
while(right+1<count2 && number2[right+1]<=number1[x]+K+5)未越界且右边一个数在区间内右移动
{
right++;
}
while(number2[left]+3+K<number1[x])左边不存在数则向左移
{
left++;
}
result += right-left+1;
*/
}
System.out.println(result);
}
}
public static boolean isletter(int index){//判断是否为空格或标点符号
if (index<0||index>=length){
return false;
}
char a=text.charAt(index);//传入下标并得到对应下标的值
return (a>='a'&&a<='z')||(a>='A'&&a<='Z');
}
}