题目链接: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 }
时间: 2024-12-13 01:07:24