CF119D

还是一道很综合的 string 练手题。

先来分析一下,将 B 按照答案分成三段,三段与 A 都有什么关系。

第一段:A 的一个子串。

第二段:A 的一段后缀翻转。

第三段:A 的一段前缀翻转。

我们大概率是要枚举其中一个的,其中第三段都能用 A,B 的前后缀表示,考虑枚举它,也就是枚举 i

下令 len|A|

然后考虑怎样处理剩下的。发现此时第一段在 A,B 中的左端点都已经确定(分别是 i+1,0)。于是可以考虑求出 L=lcp(A[i+1,len1],B[0,len1])。剩下的要求就是 jL,A[i+j+1,len1]=R(B[j,leni2])。这可以看作一个和上面类似的东西,但是前面那个可以用拓展 kmp 求的东西和 kmp 是相关联的。可以得到这个式子等价于 lcp(A[i+1,len1],B[0,len1])+maxpos(leni2)leni1。其中 maxpos(x) 为以 R(A) 为模式串,B 为文本串做 kmp,遍历到文本串第 x 位时,模式串匹配了多长。于是做完了。

但是我没用 exkmp,用的是字符串 hash。

code:

点击查看代码
const int base[2]={13331,131313},mod[2]={(int)1e9+9,469762049};
int n,m,c[207][2],fail[N],pre[N],suf[N],f[N][2],g[N][2],pw[N][2];
char s[N],t[N],r[N];
mt19937 rnd(time(0));
void readStr(char *s,int &n){
	char c=gc();
	while(c<32||c>126)c=gc();
	while(c>=32&&c<=126)s[++n]=c,c=gc();
}
il pair<ll,ll> getHashf(int l,int r){
	if(l>r)return Mp(0,0);
	return Mp((f[r][0]-1ll*f[l-1][0]*pw[r-l+1][0]%mod[0]+mod[0])%mod[0],(f[r][1]-1ll*f[l-1][1]*pw[r-l+1][1]%mod[1]+mod[1])%mod[1]);
}
il pair<ll,ll> getHashg(int l,int r){
	if(l>r)return Mp(0,0);
	return Mp((g[r][0]-1ll*g[l-1][0]*pw[r-l+1][0]%mod[0]+mod[0])%mod[0],(g[r][1]-1ll*g[l-1][1]*pw[r-l+1][1]%mod[1]+mod[1])%mod[1]);
}
void Yorushika(){
	readStr(s,n),readStr(t,m);
	if(n!=m){puts("-1 -1");return;}
	rep(i,1,150)c[i][0]=c[i][1]=i;
	pw[0][0]=pw[0][1]=1;
	rep(i,1,n)rep(j,0,1){
		f[i][j]=(1ll*f[i-1][j]*base[j]+c[s[i]][j])%mod[j];
		g[i][j]=(1ll*g[i-1][j]*base[j]+c[t[i]][j])%mod[j];
		pw[i][j]=1ll*pw[i-1][j]*base[j]%mod[j];
	}
	rep(i,1,n){
		int l=0,r=n-i+1;
		pre[i]=0;
		while(l<=r){
			int mid=(l+r)>>1;
			if(getHashf(i,i+mid-1)==getHashg(1,mid))l=(pre[i]=mid)+1;
			else r=mid-1;
		}
	}
	rep(i,1,n)r[i]=s[n-i+1];
	rep(i,2,n){
		int &j=(fail[i]=fail[i-1]);
		while(j&&r[i]!=r[j+1])j=fail[j];
		j+=r[i]==r[j+1];
	}
	rep(i,1,n){
		int &j=(suf[i]=suf[i-1]);
		while(j&&t[i]!=r[j+1])j=fail[j];
		j+=t[i]==r[j+1];
	}
	int p=0;
	while(p<n&&s[p+1]==t[n-p])p++;
	drep(i,min(p,n-1),1){
		if(s[i]!=t[n-i+1])break;
		if(pre[i+1]+suf[n-i]>=n-i)return printf("%d %d\n",i-1,n-suf[n-i]),void();
	}
	puts("-1 -1");
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)
		Yorushika();
}
posted @   yinhee  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示