Codeforces 526D - Om Nom and Necklace 【KMP】

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。

 

其中有两个疑点、

  1. 为什么A的长度要尽量小
  2. 为什么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;
}

 

posted @ 2015-04-10 14:39  zhyfzy  阅读(784)  评论(0编辑  收藏  举报