英文作文

详细题目

链接:https://ac.nowcoder.com/acm/contest/11223/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

在写英语作文的时候,两个相同单词靠的太近肯定不好。现在 ZHR 给了你一段nnn个单词的英文,问你有多少对相同单词中间间隔的单词数小于等于kkk 。

输入描述:

1
2
3
4
第一行两个整数,为n和k 。

第二行n个由仅小写字母组成的单词。每个单词长度小于等于10 。
1≤k≤n≤105

输出描述:

1
一行一个正整数,表示有多少对单词中间间隔的单词数小于等于kkk 。

示例1

输入

复制

1
2
11 2
i love you you love mi mixue ice cream and tea

输出

复制

1
2

说明

1
只有 you 和 love 两个单词间隔的单词数小于等于222

示例2

输入

复制

1
2
10 2
a a a a a a a a a a

输出

复制

1
24

笔者解析

  1. 本题使用暴力解法超时,笔者因为暴力而罚时-3
  2. 本题宜采取哈希表+滑动窗口的模式,来计算合法范围内的相同对数
  3. 使用res+=此字符串出现次数-1的方式,来计算此字符在范围内的出现次数

笔者代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;
const int N = 1e5+10;
typedef long long LL;
map<string,int>q;
string s[N];
int n,k;
int main()
{
scanf("%d%d", &n, &k);
k+=2;
for(int i=1;i<=n;i++) cin>>s[i];
LL res=0;
for(int i=1;i<=n;i++)
{
if(i<=k)
{
q[s[i]]++;
if(q[s[i]]>1) res+=q[s[i]]-1;
}
else
{
//当余下的长度,或本来的长度大于k,使用滑动窗口算法
//记录开头的数字s[i-k]个数减一在窗口数组中,相当于向右滑动的初始
q[s[i-k]]--;
//记录结尾的数字s[i]个数加一在窗口数组中,相当于向右滑动结尾
q[s[i]]++;
//s[i]的数目大于1时,则窗口范围内数组对数个数为s[i]的数目减一
if(q[s[i]]>1) res+=q[s[i]]-1;
}
}
printf("%lld\n",res);
return 0;
}