首页 > 代码库 > 【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ
【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ
枚举每个位置,给每个串的前半部分一个哈希值,后半部分一个哈希值,若是它们均相等,则视为这两个串相似。
每次转移之后,排序一下就行了。
O(L*n*log(n))。
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;typedef unsigned long long ull;struct HASH{ull l,r;}hss[30001],tmp[30001];bool operator < (const HASH &a,const HASH &b){return a.l!=b.l ? a.l<b.l : a.r<b.r;}bool operator != (const HASH &a,const HASH &b){return (a.l!=b.l||a.r!=b.r);}ull seed,seeds[201];int ord[301],n,m,ans;char s[30001][201];void init(){ if(seed==2) ord[‘0‘]=1,ord[‘1‘]=2; else { int en=0; for(char c=‘A‘;c<=‘Z‘;++c) ord[c]=++en; for(char c=‘a‘;c<=‘z‘;++c) ord[c]=++en; for(char c=‘0‘;c<=‘9‘;++c) ord[c]=++en; ord[‘_‘]=++en; ord[‘@‘]=++en; } ++seed; seeds[0]=1; for(int i=1;i<=m;++i) seeds[i]=seeds[i-1]*seed;}int main(){ scanf("%d%d",&n,&m); cin>>seed; init(); for(int i=1;i<=n;++i) { scanf("%s",s[i]); for(int j=1;j<m;++j) hss[i].r=hss[i].r*seed+(ull)ord[s[i][j]]; } memcpy(tmp,hss,(n+1)*sizeof(HASH)); for(int i=1;i<=m;++i) { int head; sort(hss+1,hss+n+1); for(int j=1;j<=n;++j) { tmp[j].l=tmp[j].l*seed+(ull)ord[s[j][i-1]]; tmp[j].r-=seeds[m-1-i]*(ull)ord[s[j][i]]; if(j==1 || hss[j]!=hss[j-1]) head=j; if(j==n || hss[j]!=hss[j+1]) ans+=(((j-head+1)*(j-head))>>1); } memcpy(hss,tmp,(n+1)*sizeof(HASH)); } printf("%d\n",ans); return 0;}
【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。