JZOJ 3870. 【NOIP2014八校联考第4场第1试10.19】单词检索(search)

Description

小可可是学校图书馆的管理员,现在他接手了一个十分棘手的任务。
由于学校需要一些材料,校长需要在文章中检索一些信息。校长一共给了小可可N篇文章,每篇文章为一个字符串。现在,校长需要他找到这样的单词,它至少在这N篇文章中的M篇文章里出现过,且单词长度为L。可是,工作量十分庞大,但校长又急需小可可完成这项任务。
现在他向你求助,需要你编写程序完成这项艰巨的任务。

Input

第1行3个正整数N,M,L,表示文章的数目,单词至少出现在M篇文章中和每个单词的长度。
接下来N行,每行一个字符串,表示一篇文章。

Output

仅一行,表示满足检索条件的单词数。

Sample Input

3 2 2
noip
istudycpp
imacppstudent

Sample Output

5
【样例解释】
这5个单词分别为:st,tu,ud,pp,cp。

Data Constraint

对于20%的数据有 1N,M10
对于60%的数据有 1N,M100
对于100%的数据有 1N,M2000L1000 。每篇文章长度不大于1000,均有小
写字母组成。

Solution

  • 这题是典型的 字符串Hash ,开散列。

  • 先枚举每篇文章,在枚举其中的每个单词,把单词转换成模意义下26进制,质数取 109+7

  • 之后把这个数放进 Hash 表中,判断是否存在,达到m次即答案+1,上限取 2106

枚举过程中注意边加边判断,总时间复杂度为 O(N(NL))

Code

#include<cstdio>
#include<cstring>
using namespace std;
const int N=1002,M=N*N*2,mo=1e9+7;
int n,m,l,ans;
int f[M],g[M];
long long p[N],h[M];
char s[N];
inline int hash(int x)
{
    int y=x%M;
    while(h[y] && h[y]!=x) y=(y+1)%M;
    return y;
}
int main()
{
    scanf("%d%d%d",&n,&m,&l);
    for(int i=p[0]=1;i<l;i++) p[i]=p[i-1]*26%mo;
    n++;
    while(--n)
    {
        scanf("%s",s+1);
        int len=strlen(s+1);
        long long sum=0;
        for(int i=1;i<l;i++) sum=(sum+p[l-1-i]*s[i])%mo;
        for(int i=l;i<=len;i++)
        {
            sum=(sum+mo-p[l-1]*s[i-l]%mo)%mo;
            sum=(sum*26+s[i])%mo;
            int k=hash(sum);
            h[k]=sum;
            if(g[k]!=n)
            {
                if(++f[k]==m) ans++;
                g[k]=n;
            }
        }
    }
    printf("%d",ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值