您的位置:首页 > 其它

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

2017-01-16 20:19 441 查看

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%的数据有 1≤N,M≤10;

对于60%的数据有 1≤N,M≤100;

对于100%的数据有 1≤N,M≤2000,L≤1000。每篇文章长度不大于1000,均有小

写字母组成。

Solution

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

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

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

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

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
,h[M];
char s
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐