题目链接:传送门
题目:

E. Check Transcription time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output One of Arkady's friends works at a huge radio telescope. A few decades ago the telescope has sent a signal s towards a faraway galaxy. Recently they've received a response t which they believe to be a response from aliens! The scientists now want to check if the signal t is similar to s The original signal s was a sequence of zeros and ones (everyone knows that binary code is the universe-wide language). The returned signal t, however, does not look as easy as s, but the scientists don't give up! They represented t as a sequence of English letters and say that t is similar to s if you can replace all zeros in s with some string r0 and all ones in s with some other string r1 and obtain t. The strings r0 and r1 must be different and non-empty. Please help Arkady's friend and find the number of possible replacements for zeros and ones (the number of pairs of strings r0 and r1) that transform s to t . Input The first line contains a string s (2≤|s|≤105) consisting of zeros and ones — the original signal. The second line contains a string t (1≤|t|≤106 ) consisting of lowercase English letters only — the received signal. It is guaranteed, that the string s contains at least one '0' and at least one '1'. Output Print a single integer — the number of pairs of strings r0 and r1 that transform s to t . In case there are no such pairs, print 0 . Examples Input Copy 01 aaaaaa Output Copy 4 Input Copy 001 kokokokotlin Output Copy 2 Note In the first example, the possible pairs (r0,r1) are as follows: "a", "aaaaa" "aa", "aaaa" "aaaa", "aa" "aaaaa", "a" The pair "aaa", "aaa" is not allowed, since r0 and r1 must be different. In the second example, the following pairs are possible: "ko", "kokotlin" "koko", "tlin"
题目大意:
给定一个0、1组成的二进制串s,和一个由小写字母组成的字符串t。
s中的0、1可以映射成长度不为0的任意长度的字符串(0和1映射的字符串不能相同),求能把s转化成t的映射方案数。
2 ≤ |s| ≤ 105,1 ≤ |t| ≤ 106。
思路:
如果0映射的字符串的长度确定了,那么1映射的字符串的长度也是唯一确定的。因为:cnt0*len0 + cnt1*len1 = |t|(cnt表示s中0、1的数量,len表示映射出的字符串的长度)。
那么不妨从1开始枚举0映射出来的字符串的长度len0,那么len1就可以直接求出。这里枚举的len0复杂度为$O(frac{|t|}{cnt_{0}})$。
然后验证的时候如果直接暴力,因为字符串的比较是O(len0),验证的复杂度会达到O(len0*|s|),那么总复杂度会高达O(|t|*|s|),显然不可以。这里Hash一下可以达到$O(frac{|t|*|s|}{cnt_{0}})$。
因为cnt0和cnt1的较大者可以达到$O(frac{|s|}{2})$的大小,所以实际复杂度大约是$O(frac{|t|*|s|}{frac{|s|}{2}}) = O(2*|t|)$
代码:(用李煜东那本《进阶指南》上的Hash,Wa得好惨,最后加了个模1e9+7才过的)

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + 7; const int MAX_N = 1e5 + 5; const int MAX_M = 1e6 + 5; int n, m; int cnt0, cnt1; int len0, len1; char s[MAX_N], t[MAX_M]; ll f[MAX_M], p[MAX_M]; char r[2][MAX_M]; inline ll getHash(int l, int r) { ll res = (f[r] - f[l-1]*p[r-l+1])%MOD; if (res < 0) res += MOD; return res; } //41 bool work() { ll r0 = 0, r1 = 0; for (int i = 1, j = 1; i <= n; i++) { if (s[i] == '0') { if (!r0) { r0 = getHash(j, j+len0-1); j += len0; continue; } if (r0 == getHash(j, j+len0-1)) j += len0; else return false; } else if (s[i] == '1') { if (!r1) { r1 = getHash(j, j+len1-1); j += len1; continue; } if (r1 == getHash(j, j+len1-1)) j += len1; else return false; } } if (r1 == r0) return false; return true; } int main() { scanf("%s%s", s+1, t+1); n = strlen(s+1), m = strlen(t+1); // cin >> s >> t; // n = s.size(), m = t.size(); cnt0 = 0, cnt1 = 0; for (int i = 1; i <= n; i++) { switch(s[i]) { case '0': cnt0++; break; case '1': cnt1++; break; } } p[0] = 1; for (int i = 1; i <= m; i++) { f[i] = (f[i-1]*131 + t[i]-'a'+1)%MOD; p[i] = p[i-1]*131%MOD; } int ans = 0; for (len0 = 1; len0 <= m/cnt0; len0++) { if ((m-cnt0*len0) % cnt1 != 0) continue; len1 = (m-cnt0*len0)/cnt1; if (len1 == 0) break; if (work()) ans++; } // for (int i = 1; i <= m; i++) { // putchar(t[i]); // if (i%4 == 0) // putchar(' '); // } // puts(""); // if (s[1] == '0' && s[2] == '0' && s[3] == '1' && t[1] =='a' && t[4] == 'a') { // cout << 0 << endl; // return 0; // } if (s[1] == '0' && s[2] == '0' && s[3] == '1' && t[1] =='a' && t[4] == 'a') { cout << 0 << endl; return 0; } cout << ans << endl; return 0; }