蓝桥杯 2019年人物相关性分析 小明正在分析一本小说中的人物相关性。 他想知道在小说中 Alice 和 Bob 有多少次同时出现。 更准确的说, 小明定义 Alice 和 Bob “同时出现”的

人物相关性分析 2019年

【问题描述】 小明正在分析一本小说中的人物相关性。 他想知道在小说中 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 。

运用差分和前缀和进行求解:

大致思路点
如果有标点符号多种,记得稍微修改一下判断条件。此处标点以:" " , . 若有?!等自行修改if条件


import java.util.ArrayList;
import java.util.Scanner;
/**
 * @version v-1.8.0_131.
 * @auther Jack hou  Email:256595662@qq.com
 * @data 2021/3/28/16:42
 * @Description:人物相关性2019,差分,前缀和。
 **/
public class 人物相关性2019 {
public static void main(String[] args) {
	Scanner scanner=new Scanner(System.in);
	int k=scanner.nextInt();
	scanner.nextLine();
	String s=scanner.nextLine();
	char[] c=s.toCharArray();//可以不给定确定的char[]数组大小,直接用toCharArray()给char[]数组赋值
	ArrayList<Integer> Al=new ArrayList<Integer>();//储存Alice出现的位置的下标
	ArrayList<Integer> Bo=new ArrayList<Integer>();
	
	 for (int i = 0; i <c.length ; i++) {
         if ((i-1<0||c[i-1]=='.'||c[i-1]==' ')&&c[i]=='A'&&c[i+1]=='l'&&c[i+2]=='i'&&c[i+3]=='c'&&c[i+4]=='e'&&(c[i+5]=='.'||c[i+5]==' ')){
        	 	//i-1<0||c[i-1]=='.'||c[i-1]==' '当i为第一项,或Alice前面没有字母且后面也没有字母,则Alice才为有效的独立Alice
        		 
        	 Al.add(i);//将Alice出现的i位置加入到ArrayList中
         }
     }
     for (int i = 0; i <c.length ; i++) {
         if ((i-1<0||c[i-1]=='.'||c[i-1]==' ')&&c[i]=='B'&&c[i+1]=='o'&&c[i+2]=='b'&&(c[i+3]=='.'&&c[i+3]=='.')){
             Bo.add(i);
         }
     }
     long ans=0;
     int CF[]=new int[1000006];//差分数组
     int QZH[]=new int[1000006];//前缀和数组
     for(int t:Al) {
    	 CF[Math.max(0,t-k-3)]++;//差分操作:对区间端点进行左端点++,区间右端点--,可以使得此区间内原本元素都加一,不是差分都加一,只有端点进行操作,左端点差分为:1,右端点为-1,中间差分元素都为0.
    	 CF[Math.min(1000000, t+k+5)]--;
     }
     QZH[0]=CF[0];
     for (int i = 1; i < 1000006; i++) {
		QZH[i]=QZH[i-1]+CF[i];//进行前缀和计算,由于这里前缀和元素原本都为0,所以加一后为1,在区间重叠部分加两次会变成2
	}
     for(int t:Bo) {
    	 ans+=QZH[t];//有多少个Bob,就有多少个相关性答案,既包含了区间不重叠的普通情况1,也包含了区间重叠产生的2.
     }
     System.out.println(ans);
}
}

原创不易,点点赞吧。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值