【问题描述】
小明正在分析一本小说中的人物相关性。他想知道在小说中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
public class Main {
// 人物相关性分析
public static int k;
public static long res = 0;
public static String text;
public static int len;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
sc.nextLine();
text = sc.nextLine();
len = text.length();
int[] num1 = new int[1000000];
int[] num2 = new int[1000000];
sc.close();
int count1 = 0, count2 = 0;
for (int i = 0; i < len; i++) {
if (!isLetter(i - 1)&&i+4<len && !isLetter(i + 5) && text.substring(i, i + 5).equals("Alice")) {
num1[count1++] = i;
}
if (!isLetter(i - 1) &&i+2<len&& !isLetter(i + 3) && text.substring(i, i + 3).equals("Bob")) {
num2[count2++] = i;
}
}
/*
if (count1 == 0 || count2 == 0)
res = 0;
else {
int left=0,right=-1;
//以Alice为目标对象,查看其附近是否有Bob
遍历每一个Alice,每一个Alice都有一个区间是所有的Bob都是可以组合的
那么我们就使用right和left来表示这个区间,然后遍历每一个Alice的时候
区间也会随着移动改变,这样算法复杂度接近线性,所以能通过的
for(int i=0;i<count1;i++) {
while(right+1<count2&&num2[right+1]<num1[i]+k+5) {
right++;
}
while(num2[left]+3+k<num1[i]) {
left++;
}
res+=right-left+1;
}
}
*/
if (count2 != 0 && count1 != 0) {
int index_Bob=0;
// left,right是围绕Alice左右的一个范围
for (int i = 0; i < count1; i++) {
for(int j=0;j<count2;j++) {
//Bob在Alice前或后的有效范围
if(num2[j]>=num1[i]-k-3&&num2[j]<=num1[i]+k+5) {
res++;
}
}
}
}
System.out.println(res);
}
public static boolean isLetter(int index) {
if(index<0||index>=len)return false;
char c=text.charAt(index);
return (c>='a' &&c<='z')||(c>='A'&&c<='Z');
}
}