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;

}

 

你可能感兴趣的:(codeforces)