CF1056E Check Transcription 题解

Codeforces
Luogu

Description.

给定一个 \(01\)\(s\),保证至少有一个 \(0\)\(1\),有一个目标串 \(t\)
问有多少种字符串 \(r_0,r_1\),使得把 \(s\)\(0\) 替换成 \(r_0\)\(1\) 替换成 \(r_1\) 后与 \(t\) 相同。

Solution.

设第一个串是 \(0\),方便处理,\(1\) 同理。
枚举 \(|r_0|\),这样 \(r_0\) 确定了,\(|r_1|=\frac{n-c_0\cdot |r_0|}{c_1}\)
考虑如果算出来的 \(|r_1|\in\mathbb N\),我们就暴力枚举一遍 \(s\),暴力判断所有的 \(s\) 能否匹配。
复杂度算一下发现是 \(O(n\ln n)\) 的,考虑所有长度都不相同,复杂度是 \(O(\frac mi)\),就变成调和级数了。

Coding.

点击查看代码
//Coded by leapfrog on 2021.11.05 {{{
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
const int N=100005,P=1019260817;char s[N],t[N*10];int n,m;
struct Hash
{
	int has;inline int pls(int x,int y) {return (x+=y)>=P?x-=P:x;}
	inline int mns(int x,int y) {return y?pls(x,P-y):x;}
	inline bool operator<(const Hash &b) {return has<b.has;}
	inline bool operator==(const Hash &b) {return has==b.has;}
	inline bool operator!=(const Hash &b) {return has!=b.has;}
	inline Hash operator+(const Hash &b) {return(Hash){pls(has,b.has)};}
	inline Hash operator-(const Hash &b) {return(Hash){mns(has,b.has)};}
	inline Hash operator*(const Hash &b) {return(Hash){int(1ll*has*b.has%P)};}
	inline Hash operator+(const int &x) {return(Hash){pls(has,x)};}
	inline Hash operator*(const int &x) {return(Hash){int(1ll*has*x%P)};}
}B=(Hash){137},pw[N*10],hs[N*10];
inline Hash geths(int l,int r) {return hs[r]-hs[l-1]*pw[r-l+1];}
int main()
{
	scanf("%s%s",s+1,t+1),n=strlen(s+1),m=strlen(t+1);
	int rs=0;for(int i=n;i>=1;i--) s[i]^=s[1];
	pw[0]=(Hash){1};for(int i=1;i<=m;i++) pw[i]=pw[i-1]*B,hs[i]=hs[i-1]*B+t[i];
	int c0=0,c1=0;for(int i=1;i<=n;i++) c0+=!s[i],c1+=s[i];
	for(int l0=1;l0<m;l0++)
	{
		if(m-c0*l0<0) break;else if((m-c0*l0)%c1) continue;
		int l1=(m-c0*l0)/c1,L0=-1,R0,L1=-1,R1;char fg=0;if(l1==0) continue;
		for(int i=1,nw=1;i<=n&&!fg;i++)
		{
			if(s[i]) if(L1==-1) L1=nw,R1=(nw+=l1)-1;else fg|=geths(L1,R1)!=geths(nw,nw+l1-1),nw+=l1;
			else if(L0==-1) L0=nw,R0=(nw+=l0)-1;else fg|=geths(L0,R0)!=geths(nw,nw+l0-1),nw+=l0;
		}rs+=!fg&&(geths(L0,R0)!=geths(L1,R1));
	}return printf("%d\n",rs),0;
}
posted @ 2021-11-05 11:48  Peal_Frog  阅读(29)  评论(0编辑  收藏  举报