人物相关性分析——第十届蓝桥杯省赛C组

尺取法(双指针)

人物相关性分析 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 个字符。 注意 :

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
【评测用例规模与约定】 对于所有评测用例, 1 ≤ K ≤ 1000000 。

思路:

按照平常思考,我们会用枚举,先计算字符串中出现的每一个Alice的位置,利用双重循环计算每个Alice与每一个Bob的位置,当两位置相差不到K,则计数加一。但这样的方法时间复杂度可达到10^12 ,必定超时。

所以需要灵活运用枚举,稍稍改变一下思路。

我们可以考虑当发现第一个Alice时,位置记作A1,则当Bob出现在[A1-K-3,A1+5+K]范围内时,出现几个就记多少次。(这个范围是因为题中按字符来算,我们需要考虑Alice和Bob的字符长度)

同理,出现第二个Alice时,位置记作A2,按照上面相同的方法计算出现多少次。

这样就从遍历全部字符串改变成遍历一个移动区间。

代码如下:

#include
#include
int main(){
    char s[1000001];
    int numa=0,numb=0;
    int i,j,k;
    long alice[1000001];
    long bob[1000001];
    int ans=0;
    int rp=0;
    int lp=0;
    scanf("%d\n",&k);
    gets(s);
    for(i=0;i<strlen(s);i++){  
      	if((i-1<0||s[i-1]=='.'||s[i-1]==' ')&&s[i]=='A'&&s[i+1]=='l'&&s[i+2]=='i'&&s[i+3]=='c'&&s[i+4]=='e'&&(s[i+5]=='.'||s[i+5]==' ')){
            alice[numa]=i;
            numa++;
        }
    	if((i-1<0||s[i-1]=='.'||s[i-1]==' ')&&s[i]=='B'&&s[i+1]=='o'&&s[i+2]=='b'&&(s[i+3]=='.'||s[i+3]==' ')){
            bob[numb]=i;
            numb++;
    	}
    }
    for(j=0;j<numa;j++){
        while(bob[lp]<alice[j]-k-3)lp++;//如果左边Bob的位置不在区间内,则将下一个Bob的位置与区间进行比对,直到区间中有第一个Bob
        while(bob[rp+1]<=alice[j]+k+5)rp++;//如果右边Bob的位置还在区间内,可尝试看下一个Bob是否也在区间内,直到下一个Bob的位置不在区间内,则区间中的Bob数就可以用rp-lp+1得出
        if(rp-lp+1>0)
            ans+=(rp-lp+1);
    }
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(蓝桥杯,c语言)