有一天,欧姆诺姆发现了一串长度为n的宝石串,上面有五颜六色的宝石。他决定摘取前面若干个宝石来做成一个漂亮的项链。
他对漂亮的项链是这样定义的,现在有一条项链S,当S=A+B+A+B+A+...+A+B+A的时候是漂亮的,这儿A,B是一些宝石串,“+”表示连接操作。S中有k+1个A和k个B组成。A和B可能是空串。
现在给出宝石串,问怎么切前几个才能得到一个漂亮的宝石项链。他切下来之后不会改变宝石的顺序。
样例解释:
在这个样例中前6个可以组成漂亮的串( A="", B="bca")。前7个也可以(A="b", B="ca")。
单组测试数据。 第一行有两个整数n, k (1≤n,k≤1 000 000),表示宝石串原始的长度和在上文中提到的参数k。 第二行有n个由小写字母组成的串,表示原始宝石串。
输出一行有n个01组成的字符串。第i(1≤i≤n)个位置是1的时候表示前i个宝石可以组成漂亮的宝石项链。
样例输入1 7 2 bcabcab
样例输出1 0000011
做这题,首先需要知道−>字符S的循环节个数=n/(n−next[n])
当n%(n−next[n])==0时,字符串S可以被分为n/(n−next[n])段相同字符串
当n%(n−next[n])!=0时,S[next[n]...n−1]是S的前缀时,形如abcabcab,n/(n−next[n])=2
于是原字符串P,可以被划分为SSS..SSST形式的串,T是S的前缀 ,S,T可为空
令num=n/(n−next[n]),num即是S的数量
当n%(n−next[n])==0时,T为空,P=SSS...SSS
假设A包含a个S,B包含b个S
题目要求形如ABABABABA...的形式,可看为K个AB,再加上一个A
令a=num%k,a+b=num/k,则满足(a+b)∗k+a∗k=num
于是有:num%k>=0且num/k>=0 (A,B长度>=0)即可
当n%(n−next[n])!=0时,P=SSS...SSST
此时假设A=T,B=(S−T)+SSS...SSS
同上将AB看成整体,a+b=num/k,a=num%k
因为T为S前缀且T!=S,B必定不为空,所以num/k−num%k>0
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
//const int inf=0x3f3f3f3f;
const int N = 1e6+5;
const int MAXN=N;
void kmp_pre(const char x[],int m,int next[])
{
int i,j;
j=next[0]=-1;
i=0;
while(i<m)
{
while(-1!=j && x[i]!=x[j])j=next[j];
next[++i]=++j;
}
}
char str[N];
int Next[N];
char ans[N];
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
int n,k;
while(~scanf("%d%d%s",&n,&k,str)){
kmp_pre(str,n,Next);
MEM(ans,'0');
for(int len=1;len<=n;++len){
int num=len/(len-Next[len]);
if(len%(len-Next[len])){
if(num/k-num%k>0){
ans[len-1]='1';
}
}
else{
if(num/k-num%k>=0){
ans[len-1]='1';
}
}
}
ans[n]=0;
puts(ans);
}
return 0;
}