ZeptoLab Code Rush 2015
D. Om Nom and Necklace
【题意】
给出一个字符串s,判断其各个前缀是否是 ABABA…ABA的形式(A和B都可以为空,且A有Q+1个,B有Q个,Q给定)。
【官方题解】
对于前缀P,我们可以把它拆成P=SSSS…SSSST,其中T是S的前缀。显然可以用KMP算法,时间复杂度是O(n)。
当T=S:P=SSS…S。假设S出现了R次。如果转换为ABABAB…ABABA的形式,A和B是由几个S组成,而且最后的A一定是P的一个后缀。由贪心算法,A的长度尽量小,所以A中S出现R mod Q次。B中S出现R/Q-R mod Q次。因为只需判断R/Q-R mod Q>=0即可
当T!=S:由于上一种方法类似,A可以是SSS…ST,因为它的长度尽量小,所以我们只需判断是否R/Q-R mod Q>0。
其中有两个疑点、
- 为什么A的长度要尽量小
- 为什么A中有R mod Q个S,B中有R/Q-R mod Q 个S
因为要将字符串P=SSSS…SS 分成ABABABA…ABA的形式(Q+1个A,Q个B),相当于Q份AB再附加上一个A,我们让AB尽量长,那么最后的A一定是尽量小。
那么每份AB中有R/Q个S,而多余的R%Q则归属于A,因此可以推导出B有R/Q-R%Q个S。
当T=S时,B可以为空,所以满足R/Q-R%Q>=0即可。
当T!=S时,B不可以为空(A是AB的一个前缀,并且T是A的一个后缀,是S的一个前缀,由于T!=S,至少需要一些字符把T补成完整的S。所以B不可以为空),这是判断是否满足R/Q-R%Q>0即可。
#include<bits/stdc++.h> #define eps 1e-9 #define FOR(i,j,k) for(int i=j;i<=k;i++) #define MAXN 1000005 #define MAXM 40005 #define INF 0x3fffffff using namespace std; typedef long long LL; int i,j,k,n,m,x,y,T,big,cas,num,len; bool flag; int next[MAXN],ans[MAXN]; char s[MAXN]; int main() { scanf("%d%d",&n,&k); scanf("%s",s); len=strlen(s); next[0]=0; j=0; if (k==1) ans[0]=1; for (i=1;i<len;i++) { j=next[i]; while (j && s[i]!=s[j]) j=next[j]; if (s[i]==s[j]) j++; else j=0; next[i+1]=j; int size=i+1-next[i+1]; if ((i+1)%size==0) { int R=(i+1)/size; if (R/k>=R%k) ans[i]=1; }else { int R=(i+1)/size; if (R/k>R%k) ans[i]=1; } } for (i=0;i<len;i++) printf("%d",ans[i]); printf("\n"); return 0; }
时间: 2024-10-11 05:27:21