2023牛客暑期多校训练营8-I Make It Square
https://ac.nowcoder.com/acm/contest/57362/I
文章目录
- 2023牛客暑期多校训练营8-I Make It Square
- 题意
- 解题思路
- 代码实现
题意
解题思路
这里有两种情况,即 ∣ 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 t1−t2/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]<<' ';
}