题意
给你一个01串a,字符串b,将0用x字符串表示,1用y字符串表示,用a字符串的规则排列xy使得与b字符串相等,问有几种方法
思路
我们枚举0字符串x的长度,对于一个给定的长度,我们都能求出1对应的字符串的长度,然后我们定义一个l=0,表示b字符串的其实位置,我们遍历a字符串,对于对应的0与1,我们在b字符串中求出相应的hash值,将求出的hash值与hash0与hash1做比较,如果不相同那么肯定不行。
防ull溢出的解决方法是取模
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN=1e6+10;
typedef long long ll;
char str1[MAXN],str2[MAXN];
ll xp[MAXN],hash_2[MAXN];
const int seed=13331;
const int mod=1000000007;
void init()
{
xp[0]=1;
for(int i=1;i<MAXN;i++)
xp[i]=(xp[i-1]*seed)%mod;
}
ll get_hash(int i,int l)
{
return ((hash_2[i]-hash_2[i+l]*xp[l])%mod+mod)%mod;
}
int main()
{
init();
scanf("%s%s",str1,str2);
int numa=0,numb=0;
int lena=strlen(str1);
int lenb=strlen(str2);
for(int i=0;i<lena;i++)
if(str1[i]=='0') numa++;
else numb++;
hash_2[lenb]=0;
for(int i=lenb-1;i>=0;i--)
hash_2[i]=(hash_2[i+1]*seed+str2[i]-'a'+1)%mod;
int ans1=0;
for(int i=1;i<=lenb;i++)
{
if(numa*i>lenb) break;
int b=(lenb-numa*i);
if(b<numb||b%numb!=0) continue;
b/=numb;
ll hash0=0,hash1=0;
int l=0;
int fg=1;
for(int j=0;j<lena;j++)
{
if(str1[j]=='0')
{
ll t=get_hash(l,i);
if(!hash0) hash0=t;
else
{
if(hash0!=t)
{
fg=0;
break;
}
}
l+=i;
}
else if(str1[j]=='1')
{
ll t=get_hash(l,b);
if(!hash1) hash1=t;
else
{
if(hash1!=t)
{
fg=0;
break;
}
}
l+=b;
}
}
if(hash0==hash1) continue;
if(fg)
{
ans1++;
}
}
printf("%d\n",ans1);
return 0;
}