题意:
给你一个字符串,如果从开头到某一个位置的格式是A+B+A+B+…+A的形式,(A有k+1个,b有k个,A,B可以为空)那么这里就输出1,否则输出0.
题解:
我们将A+B看做C,那么就是C+C+C+…+A,也就是k个相同的字符串加上一个C的前缀。那么我们就用后缀数组处理出所有后缀与这整个字符串的最长前缀,记到same数组里,这样的话我们在求A的时候直接算上这个位置的same,由于A是C的子串,所以要取个min。那怎么求same数组?
我们知道height[i]是排名为i与排名为i-1的后缀的最长公共前缀,那么可以从rk[0]这个位置往两边扩出去,但是由于height数组是波澜起伏的一个数组,所以每次都要取个min,比如说有
aaa
aaaa
aab
假设整个字符串是以aab为前缀的,前面的两行是这个字符串的某一个后缀,那么height[3]=2,height[2]=3,height[1]=0,显然第一个后缀与第三个后缀的最长公共前缀是2,所以要取min。
之后我们枚举C的长度即可,查找每一段是否相等用哈希,注意它有1e6个字符串,所以单哈希和unsigned long long 自动取模都不行,或者你运气够好。反正我是用双哈希才过的,双哈希就是用一个pair,两边分别保存哈希时候乘上的不同的数,假设hash=hash*k+a[i],这个保存的就是不同的k,我这里是用31与23。
最后如果实时更新的话会T,所以我们用差分维护哪一段有即可。
但是这个方法肯定不是最佳方法,因为我是刚刚好卡过去的
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pl pair<ll,ll>
const ll mod=1e9+7;
const int N=1e6+5;
int wa[N],wb[N],wv[N],we[N],rk[N];
int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void build_sa(char *r,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[x[i]=r[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i;
for(j=1,p=1;p<n;j*=2,m=p){
for(p=0,i=n-j;i<n;i++)y[p++]=i;
for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=0;i<n;i++)wv[i]=x[y[i]];
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[wv[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
int height[N];
void calheight(char *r,int *sa,int n){
int i,j,k=0;
for(i=1;i<=n;i++)rk[sa[i]]=i;
for(i=0;i<n;height[rk[i++]]=k){
for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
}
int sa[N],same[N];
char a[N];
pl has[N],p[N];
pl get_hash(int l,int r)
{
return (pl){(has[r].first-has[l].first*p[r-l].first%mod+mod)%mod,(has[r].second-has[l].second*p[r-l].second%mod+mod)%mod};
}
int ans[N];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
scanf("%s",a);
if(k==1)
{
for(int i=1;i<=n;i++)
printf("1");
printf("\n");
return 0;
}
a[n]='0';
build_sa(a,sa,n+1,300);
calheight(a,sa,n);
int mx=height[rk[0]];
same[0]=mx;
for(int i=rk[0];height[i]>0&&i>0;i--)
same[sa[i-1]]=min(mx,height[i]),mx=min(mx,height[i]);
mx=height[rk[0]+1];
for(int i=rk[0]+1;height[i]>0&&i<n;i++)
same[sa[i]]=min(mx,height[i]),mx=min(mx,height[i]);
pl h=(pl){0,0};
p[0]={1,1};
for(int i=0;i<n;i++)
h.first=(h.first*31+(ll)a[i])%mod,h.second=(h.second*23+(ll)a[i])%mod,has[i]=h;
for(int i=1;i<=n;i++)
p[i].first=p[i-1].first*31%mod,p[i].second=p[i-1].second*23%mod;
for(int len=1;len*k<=n;len++)
{
h=has[len-1];
for(int i=1;i<k;i++)
{
if(get_hash(i*len-1,i*len+len-1)!=h)
break;
if(i==k-1)
ans[len*i+len-1]++,ans[len*i+len+min(len,same[len*i+len])]--;
}
}
int sum=0;
for(int i=0;i<n;i++)
sum+=ans[i],printf("%d",sum>0?1:0);
return 0*printf("\n");
}