1. 程式人生 > >Codeforces1056E.Check Transcription(列舉+Hash)

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