2023牛客暑期多校训练营8-I Make It Square

2023牛客暑期多校训练营8-I Make It Square

https://ac.nowcoder.com/acm/contest/57362/I

题意

在这里插入图片描述

解题思路

这里有两种情况,即 ∣ s ∣ > ∣ t ∣ |s|>|t| s>t ∣ s ∣ < ∣ t ∣ |s|<|t| s<t,首先考虑 ∣ s ∣ > ∣ t ∣ |s|>|t| s>t的情况,对于不同的 m m m,有两种情况,用图画来表示下面两种情况:
在这里插入图片描述
显然对于每一种情况都要判断 t t t是否与 s 1 s_1 s1的后缀相同。否则答案必为 0 0 0
如图,对于第一种情况,即 p p p q q q有重叠,设重叠部分有 k k k个元素,其答案显然为 2 6 k 26^k 26k;
对于第二种情况,还需要判断 s 2 s_2 s2 s 1 s_1 s1的重叠部分是否相同。
判断 s 2 s_2 s2 s 1 s_1 s1的重叠部分相同不需要一一枚举,可以发现,重叠部分即是 s s s的相同的前缀与后缀,可以用 k m p kmp kmp算法中的求 n e x t next next数组的方法来求。
而对于 ∣ s ∣ < ∣ t ∣ |s|<|t| s<t,可以发现若交换 t t t s s s,不会影响最终答案,如下图:
在这里插入图片描述
左图中,上下 s s s对应的 t t t的区域距 t t t尾部都是 p / q p/q p/q,右图中,上下 s s s对应的 t t t的区域距 t t t头部都是 t 1 − t 2 / q 1 t_1-t_2/q_1 t1t2/q1,显然 t 2 = q 2 t_2=q_2 t2=q2所以 s s s所对的区域都相同, s s s显然相同,所以交换后 1 1 1还是 1 1 1 0 0 0还是 0 0 0 2 6 k 26^k 26k还是 2 6 k 26^k 26k

代码实现

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5,mod=998244353;
int m,nx[N];
long long ans[N];
char a[N],b[N];
int main(){
	cin>>m;
	scanf("%s %s",a+1,b+1);
	int A=strlen(a+1),B=strlen(b+1);
	if((A+B)%2){
		for(int i=1;i<=m;i++)cout<<0<<' ';
		return 0;
	}
	if(A<B)swap(a,b),swap(A,B);
	int k=0,f=0;
	nx[1]=0;
	for(int i=2;i<=A;i++){
		while(k>0&&a[k+1]!=a[i])k=nx[k];
		if(a[k+1]==a[i])k++;
		nx[i]=k;
	}
	int d=(A+B)/2,r=A-d;
	for(int i=1;i<=B;i++){
		if(b[i]!=a[d-B+i]){
			for(int i=1;i<=m;i++)cout<<0<<' ';
			return 0;
		}
	}
    f=nx[A];
	while(f>0){
		if(f<r)
		ans[r-f]=1;
		f=nx[f];
	}
	ans[r]=1;
	for(int i=r+1;i<=m;i++)ans[i]=ans[i-1]*26%mod;
	for(int i=1;i<=m;i++)cout<<ans[i]<<' ';
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值