Codeforces1056E.Check Transcription(枚举+Hash)

题目链接:传送门

题目:

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" 
View Code

题目大意:

  给定一个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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Lubixiaosi-Zhaocao/p/10051095.html