Check Transcription 双哈希 扩展欧几里得

题目链接https://codeforces.com/contest/1056/problem/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 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 r 0 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 r 0  and  r1 ) that transform s to t  .

Input

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

The second line contains a string  t (1≤|t|≤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 rr0 and  r1 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 (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的字符串,第二行给一个只包含小写字母的字符串,问有多少种方案,将第一行的字符串中的0换成字符串r1,1换成字符串r2,拼成的字符串等于第二行的字符串,要求r1和r2非空,而且不相等。

我们可以先算出0的个数和1的个数,假设有a个0,b个1,第二行字符串的长度为n。

然后枚举r1的长度,假设为x,r2的长度为y。

那么x和y要满足 ax+by=n.

枚举出满足ax+by=n的x和y,然后去check这个方案是否合法,合法则答案加1.

枚举可以暴力枚举,也可以用扩展欧几里得算出所有解。

将字符串哈希一下,每次check的时候遍历一遍01字符串。

字符串哈希值取131和13331都在test17 wa了,取13332在test 25 wa了,那么哈希值取13331和13332 双哈希就就过了。

暴力枚举代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=1e6+5;
char c[maxn],s[maxn];
ull p[2]={13331,13332};
ull hs[maxn][2],f[maxn][2];
int n,m;
ull get(int l,int r){
    return hs[r][0]-hs[l-1][0]*f[r-l+1][0];
}
ull get2(int l,int r){
    return hs[r][1]-hs[l-1][1]*f[r-l+1][1];
}
bool check(int x,int y){
    ull r=0,r2=0;
    ull rr=0,rr2=0;
    int id=1;
    for(int i=1;i<=m;i++){
        if(c[i]=='0'){
            if(r==0) r=get(id,id+x-1),rr=get2(id,id+x-1);
            else if(get(id,id+x-1)!=r||get2(id,id+x-1)!=rr) return false;
            id+=x;
        }else{
            if(r2==0) r2=get(id,id+y-1),rr2=get2(id,id+y-1);
            else if(get(id,id+y-1)!=r2||get2(id,id+y-1)!=rr2) return false;
            id+=y;
        }
    }
    return !(r==r2&&rr==rr2);
}
int main(){
    scanf("%s",c+1);
    scanf("%s",s+1);
    f[0][0]=f[0][1]=1;
    n=strlen(s+1);
    for(int i=1;i<=n;i++){
        hs[i][0]=hs[i-1][0]*p[0]+s[i];
        f[i][0]=f[i-1][0]*p[0];
        hs[i][1]=hs[i-1][1]*p[1]+s[i];
        f[i][1]=f[i-1][1]*p[1];
    }
    m=strlen(c+1);
    int a=0,b=0;
    for(int i=1;i<=m;i++){
        if(c[i]=='0') a++;
        else b++;
    }
    int ans=0;
    for(int x=1;;x++){
        if(a*x>=n) break;
        if((n-a*x)%b==0){
            int y=(n-a*x)/b;
            if(check(x,y)) ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

扩展欧几里得代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1e6+5;
char c[maxn],s[maxn];
ull p[2]={13331,13332};
ull hs[maxn][2],f[maxn][2];
int n,m;
int exgcd(int a,int b,int& x,int& y){
    if(b==0) { x=1 , y=0; return a; }
    int d=exgcd(b,a%b,x,y);
    int z=x; x=y; y=z-y*1LL*(a/b);
    return d;
}
ull get(int l,int r){
    return hs[r][0]-hs[l-1][0]*f[r-l+1][0];
}
ull get2(int l,int r){
    return hs[r][1]-hs[l-1][1]*f[r-l+1][1];
}
bool check(int x,int y){
    ull r=0,r2=0;
    ull rr=0,rr2=0;
    int id=1;
    for(int i=1;i<=m;i++){
        if(c[i]=='0'){
            if(r==0) r=get(id,id+x-1),rr=get2(id,id+x-1);
            else if(get(id,id+x-1)!=r||get2(id,id+x-1)!=rr) return false;
            id+=x;
        }else{
            if(r2==0) r2=get(id,id+y-1),rr2=get2(id,id+y-1);
            else if(get(id,id+y-1)!=r2||get2(id,id+y-1)!=rr2) return false;
            id+=y;
        }
    }
    return r!=r2||rr!=rr2;
}
int main(){
    scanf("%s",c+1);
    scanf("%s",s+1);
    f[0][0]=f[0][1]=1;
    n=strlen(s+1);
    for(int i=1;i<=n;i++){
        hs[i][0]=hs[i-1][0]*p[0]+s[i];
        f[i][0]=f[i-1][0]*p[0];
        hs[i][1]=hs[i-1][1]*p[1]+s[i];
        f[i][1]=f[i-1][1]*p[1];
    }
    m=strlen(c+1);
    int a=0,b=0;
    for(int i=1;i<=m;i++){
        if(c[i]=='0') a++;
        else b++;
    }
    int ans=0;
    int d,x,y;
    d=exgcd(a,b,x,y);
    bool cnt=0;
    for(ll k=floor(-1.0*n*x/b)+1;k<ceil(1.0*n*y/a);k++){
        cnt++;
        int xx=1LL*n/d*x+k*b/d;
        int yy=1LL*n/d*y-k*a/d;
        if(check(xx,yy)) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值