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 }