首页 > 代码库 > [字符串hash] hdu 4821 String
[字符串hash] hdu 4821 String
题意:
给你M,L,再给一个串str
任意截取M*L长度的连续子串
再把这个子串分成M份长度为L的连续串
使得这M份互不相同
问有几种截取方法
思路:
考虑到子串是否相等,就运用字符串hash
用到map判重和割补的办法优化
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"map" #include"vector" #include"string" #define inf 0x7fffffff #include"iostream" using namespace std; #define ll unsigned __int64 const ll maxn=100100; ll hash[maxn],base[maxn],cnt[maxn*10]; char s[maxn]; void init(ll len) { ll seed=131; hash[0]=0; base[0]=1; for(ll i=1; i<=len; i++) { hash[i]=hash[i-1]*seed+s[i]; base[i]=base[i-1]*seed; } } ll gethash(ll L,ll R) { return hash[R]-hash[L-1]*base[R-L+1]; } int main() { ll m,l; while(scanf("%I64u%I64u",&m,&l)!=-1) { ll ans=0,lit=m*l; scanf("%s",s+1); ll len=strlen(s+1); init(len); for(ll i=1; i<=l; i++) { map<ll,ll>mark; ll sum=1,ssb=0; for(ll j=i; j<=i+lit-1; j+=l) //以首开头的 先取第一个M份 { ll tep=gethash(j,j+l-1); if(mark[tep]==0) { mark[tep]=sum++; ssb++; cnt[mark[tep]]=0; } cnt[mark[tep]]++; } if(ssb==m) ans++; for(ll j=i+lit; j+l-1<=len; j+=l) { ll tep=gethash(j-lit,j-lit+l-1); cnt[mark[tep]]--; //删掉第一份中长度L的串 if(cnt[mark[tep]]==0) { ssb--; mark[tep]=0; } tep=gethash(j,j+l-1); //加上后面长度为L的串 if(mark[tep]==0) { mark[tep]=sum++; ssb++; cnt[mark[tep]]=0; } cnt[mark[tep]]++; if(ssb==m) ans++; } } printf("%I64u\n",ans); } return 0; }
[字符串hash] hdu 4821 String
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。