Mail.Ru Cup 2018 Round 3 E. Check Transcription (字符串hash)
Mail.Ru Cup 2018 Round 3 E. Check Transcription
-
题意:给你一个\(01\)串\(s\)和一个字符串\(t\),将\(t\)中的两个不同的子串映射成\(0\)和\(1\),问你有多少种不同的映射方法使得\(s\)映射后刚好为\(t\)。
-
题解:先统计\(0\)和\(1\)的个数\(cnt0\)和\(cnt1\),假设我们映射给\(0\)的长度为\(len_0\),\(1\)为\(len_1\),有:\(cnt_0*len_0+cnt_1*len_1=|t|\),可以枚举\(len_0\)的长度,如果合法,就能得到\(len_1\)的长度,同时也自然能得到两个映射的子串,用hash去暴力check是否合法.显然这种方法看上去并没有问题,我们担心的是会不会超时.设\(c=max(cnt_0,cnt_1)\),显然\(c\ge \frac{|s|}{2}\),根据上面的公式,合法的解最多有\(\frac{|t|}{c}\)个,所以最多跑\(|t|+\frac{|t|}{c}*|s|=|t|+2*|t|\)次,前面的这个\(|t|\)应该可以优化掉,但我直接跑了,问题不大,此外这题hash自然溢出会被卡,记得取模
-
代码:
#include <bits/stdc++.h> #define ll long long #define ull unsigned long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e7 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,m; int cnt0,cnt1; string s,t; ll ans=0; ull base=19260817; ull h[N],p[N]; void init(){ p[0]=1,h[0]=0; for(int i=1;i<=m;++i){ h[i]=(h[i-1]*base+t[i])%mod; p[i]=p[i-1]*base%mod; } } ull get_hash(int l,int r){ return (h[r]-h[l-1]*p[r-l+1]%mod+mod)%mod; } int main() { cin>>s>>t; n=(int)s.size(),m=(int)t.size(); s=" "+s,t=" "+t; init(); for(int i=1;i<=n;++i){ if(s[i]=='0'){ cnt0++; } else{ cnt1++; } } for(int i=1;i<=m;++i){ int len0=i; if(m-cnt0*len0<=0) break; if((m-cnt0*len0)%cnt1==0){ int len1=(m-cnt0*len0)/cnt1; ull res0=0,res1=0; string now0,now1; int now=1; for(int j=1;j<=n;++j){ if(s[j]=='0'){ if(!res0) res0=get_hash(now,now+len0-1); now+=len0; } else{ if(!res1) res1=get_hash(now,now+len1-1); now+=len1; } } if(res0==res1) continue; bool flag=true; int pos=1; for(int j=1;j<=n;++j){ if(s[j]=='0'){ ull cur=get_hash(pos,pos+len0-1); if(cur!=res0){ flag=false; break; } pos=pos+len0; } else{ ull cur=get_hash(pos,pos+len1-1); if(cur!=res1){ flag=false; break; } pos=pos+len1; } } if(flag) ans++; } } cout<<ans<<endl; return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮