首页 > 代码库 > hdu 4821 String(字符串hash)

hdu 4821 String(字符串hash)

题目链接:hdu 4821 String

题意:

给你一个字符串,问你有多少子串,满足长度为m*len,并且这个子串能分成m个len长度的不同串。

题解:

BKDRhash+map来判重。注意的是要以len长分类来扫,这样才不会超时。

技术分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef unsigned long long ull;
 5 const int str_len=1e5+7;
 6 struct string_hash
 7 {
 8     const static int seed=31;
 9     int len;
10     ull h[str_len],b[str_len];
11     inline int idx(char x)
12     {
13         return x-a+1;
14     }
15     void init()
16     {
17         h[0]=0,b[0]=1;
18         F(i,1,str_len-1)b[i]=b[i-1]*seed;
19     }
20     void ins(char *s)//从1开始。
21     {
22         len=strlen(s+1);
23         F(i,1,len)h[i]=h[i-1]*seed+idx(s[i]);
24     }
25     inline ull ask(int l,int r){return h[r]-b[r-l+1]*h[l-1];}//区间段hash值
26 }str;
27 
28 int m,l,ans;
29 char s[str_len];
30 map<ull,int>cnt;
31 int main()
32 {
33     str.init();
34     while(~scanf("%d%d",&m,&l))
35     {
36         scanf("%s",s+1);
37         str.ins(s),ans=0;
38         for(int i=1;i<=l&&i+m*l<=str.len;i++)
39         {
40             cnt.clear();
41             for(int j=i;j<i+m*l;j+=l)cnt[str.ask(j,j+l-1)]++;
42             ans+=(cnt.size()==m);
43             for(int j=i+m*l;j+l-1<=str.len;j+=l)
44             {
45                 cnt[str.ask(j,j+l-1)]++;
46                 ull tmp;
47                 cnt[tmp=str.ask(j-m*l,j-m*l+l-1)]--;
48                 if(cnt[tmp]==0)cnt.erase(tmp);
49                 ans+=(cnt.size()==m);
50             }
51         }
52         printf("%d\n",ans);
53     }
54     return 0;
55 }
View Code

 

hdu 4821 String(字符串hash)