zoukankan      html  css  js  c++  java
  • Codeforces 1056E

    题目链接:https://codeforces.com/problemset/problem/1056/E

    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 $r_0$ and all ones in $s$ with some other string $r_1$ and obtain $t$. The strings $r_0$ and $r_1$ 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 $r_0$ and $r_1$) that transform $s$ to $t$.

    Input
    The first line contains a string $s (2 le |s| le 10^5)$ consisting of zeros and ones — the original signal.

    The second line contains a string $t (1 le |t| le 10^6)$ 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 $r_0$ and $r_1$ that transform $s$ to $t$.

    In case there are no such pairs, print 0.

    Examples
    Input
    01
    aaaaaa
    Output
    4

    Input
    001
    kokokokotlin
    Output
    2

    Note
    In the first example, the possible pairs $(r_0,r_1)$ are as follows:

    "a", "aaaaa"
    "aa", "aaaa"
    "aaaa", "aa"
    "aaaaa", "a"
    The pair "aaa", "aaa" is not allowed, since $r_0$ and $r_1$ must be different.

    In the second example, the following pairs are possible:

    "ko", "kokotlin"
    "koko", "tlin"

    题意:

    给定一个 $0,1$ 字符串 $s$,和一个小写字母组成的字符串 $t$。

    现在要找出两个互不相同且非空的字符串 $r_0, r_1$,使得将 $s$ 中的 $0$ 全部替换成 $r_0$,将 $1$ 全部替换成 $r_1$ 后,即可得到 $t$。

    要求输出不同二元组 $(r_0,r_1)$ 的数量。

    题解:

    不妨枚举 $r_0$ 的长度,这样一来,根据 $0,1$ 的数目,可以直接算出 $r_1$ 的长度。

    然后遍历 $s$,看此时假设的 $r_0$ 和 $r_1$ 是否可以成立,这个可以对 $t$ 字符串hash之后 $O(1)$ 地求出每个 $0,1$ 转换出来的 $r_0,r_1$ 符不符合要求。

    关于时间复杂度,表面上看起来时间复杂度为 $O(|s||t|)$ 的,但实际上由于要满足条件 $|t| = cnt_0 cdot |r_0| + cnt_1 cdot |r_1|$,可供选择的 $(|r_0|,|r_1|)$ 比 |t| 少很多。

    而且,对于很多的 $(|r_0|,|r_1|)$,若其对应的 $(r_0,r_1)$ 并非可行解,其实很快就能判定出来,不需要 $O(|s|)$ 次hash。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int P=131;
    const int M=1e7+7;
    const int maxs=1e5+5;
    const int maxt=1e6+5;
    
    int lens,lent;
    char s[maxs],t[maxt];
    int tot0,tot1;
    
    ll pre[maxt],Ppow[maxt];
    void prework(int len)
    {
        pre[0]=0;
        Ppow[0]=1;
        for(int i=1;i<=len;i++)
        {
            pre[i]=pre[i-1]*P+(t[i]-'a'+1), pre[i]%=M;
            Ppow[i]=Ppow[i-1]*P%M;
        }
    }
    inline ll Hash(int l,int r) {
        return (pre[r]-pre[l-1]*Ppow[r-(l-1)]%M+M)%M;
    }
    int main()
    {
        scanf("%s%s",s+1,t+1); lens=strlen(s+1), lent=strlen(t+1);
        tot0=tot1=0;
        for(int i=1;i<=lens;i++) tot0+=(s[i]=='0'), tot1+=(s[i]=='1');
    
        int ans=0;
        int len0,len1;
        prework(lent);
        for(len0=1;len0<lent;len0++)
        {
            if(tot0*len0>=lent) break;
            if((lent-tot0*len0)%tot1>0) continue;
            len1=(lent-tot0*len0)/tot1;
    
            bool ok=1;
            int cnt0=0, cnt1=0;
            ll hash_r0=0, hash_r1=0;
            for(int i=1;i<=lens;i++)
            {
                if(s[i]=='0')
                {
                    int l=cnt0*len0+cnt1*len1+1, r=l+len0-1;
                    ll has=Hash(l,r);
                    if(hash_r0==0) {
                        hash_r0=has;
                    } else {
                        if(hash_r0!=has) {
                            ok=0; break;
                        }
                    }
                    cnt0++;
                }
                if(s[i]=='1')
                {
                    int l=cnt0*len0+cnt1*len1+1, r=l+len1-1;
                    ll has=Hash(l,r);
                    if(hash_r1==0) {
                        hash_r1=has;
                    } else {
                        if(hash_r1!=has) {
                            ok=0; break;
                        }
                    }
                    cnt1++;
                }
                if(hash_r0!=0 && hash_r1!=0 && hash_r0==hash_r1) {
                    ok=0;
                    break;
                }
            }
            if(ok) ans++;
        }
        printf("%d
    ",ans);
    }

    注意:不要使用unsigned long long类型的溢出自动取模,会被卡掉;改为对大质数取模就能通过了。

  • 相关阅读:
    裸裸的spfa~嘿嘿嘿!
    睡前1小时数学系列之-整除
    拓扑排序1.奖金
    拓扑排序
    SCU 1095运送物资(最短路)
    POJ1158 城市交通Traffic lights IOI 1999 (最短路)
    POI0109 POD (最短路)
    HN0I2000最优乘车 (最短路变形)
    FOJ1205 小鼠迷宫问题 (BFD+递推)
    CJOI 05新年好 (最短路+枚举)
  • 原文地址:https://www.cnblogs.com/dilthey/p/10046828.html
Copyright © 2011-2022 走看看