hdu4821 字符串hash(有多少(M*L长的,M个不相同)子串))

题意这英语。。反正我是读不懂==

题意:给定一个串,有多少M*L的子串,其中子串的M个子串不相同=

(注:某一位不相同即为不相同)

很明显要On的扫,但是似乎前一个与后一个没有关系?是的,前第x个(x MOD len==i MOD len)才有关系,如何判重?从cp那学来的黑科技字符串hash加一个map即可,其中细节需要好好考虑==

字符串hash(from cp):

把W看成一串B进制数,B取unsigned long long 100000007,先求出W串的hash值,再逐步求出T中每|W|长的串的hash。

Hash[k+1] = Hash[k] * B - s[k] * B^|W| + s[k+|W|],s[i]表示T中第i个字符,该公式表示从k开始长为|W|的子串的hash值转移到从k+1开始长为|W|的字串的hash值的方法。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<map>
 4 #include<algorithm>
 5 using namespace std;
 6 #define uLL unsigned long long
 7 const  uLL B=1000000007;
 8 map<uLL,int>mp;
 9 char s[100005];
10 uLL has[100005];
11 int main()
12 {
13   int m,l,len,i,j,flag,ans,now;
14   uLL tmp,w;
15   while (~scanf("%d%d",&m,&l))
16   {
17     scanf("%s",s+1);
18     len=strlen(s+1);
19     //字符串hash
20     tmp=1; w=0;
21     for (i=1;i<l;i++){
22       tmp=tmp*B;
23       w=w*B+s[i]-'a'+1;
24     }
25     w=w*B+s[l]-'a'+1;
26     has[1]=w;
27     for (i=1;i<len-l+1;i++)
28       has[i+1]=(has[i]-tmp*(s[i]-'a'+1))*B+(s[i+l]-'a'+1);
29 //    for (i=1;i<=len-l+1;i++) printf("%llu\n",has[i]);
30 
31     ans=0;
32     for (i=1;i<=l;i++)
33     {
34       mp.clear(); flag=0;
35       for (j=1;j<=m;j++)
36       {
37         now=i+(j-1)*l;
38         if (now>len-l+1) break;
39         mp[has[now]]++;
40         if (mp[has[now]]==2) flag++;
41       }
42       if (now>len-l+1) break; 
43       if (flag==0) ans++;
44       for (j=m+1;;j++)
45       {
46         now=i+(j-1)*l;
47         if (now>len-l+1) break;
48         mp[has[now]]++;
49         if (mp[has[now]]==2) flag++;
50         mp[has[now-l*m]]--;
51         if (mp[has[now-l*m]]==1) flag--;
52         if (flag==0) ans++;
53       }
54     }
55     printf("%d\n",ans);
56   }
57   return 0;
58 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821

posted on 2015-02-09 00:37  xiao_xin  阅读(230)  评论(0编辑  收藏  举报

导航