人物相关性分析

【问题描述】
小明正在分析一本小说中的人物相关性。他想知道在小说中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');
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值