【BZOJ4974】【Lydsy1708月赛】—字符串大师(Kmp)

传送门

很多题解每次暴力跳failfail的复杂度确定是对的吗?
如果不是数据水应该随便卡到O(n2)O(n^2)

由于=inxt[i]最小循环节=i-nxt[i]
于是可以得到nxtnxt
如果已经得到了a[1...i1]a[1...i-1]
如果nxt[i]0nxt[i]\not =0直接赋值即可
否则需要保证不能由之前的转移
a[i]!=a[nxt[i1]+1]a[nxt[nxt[i1]]]a[nxt[nxt[nxt[i1]]]].....a[i]!=a[nxt[i-1]+1],a[nxt[nxt[i-1]]],a[nxt[nxt[nxt[i-1]]]].....
由于不能直接跳failfail所以维护一个前面所有failfail的桶即可

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>
#define chemx(a,b) ((a)<(b)?(a)=(b):0)
#define chemn(a,b) ((a)>(b)?(a)=(b):0)
cs int N=100005;
int lp[N],n,nxt[N],buc[N][27],a[N];
int main(){
	freopen("lx.cpp","r",stdin);
	n=read();
	for(int i=1;i<=n;i++)lp[i]=read(),nxt[i]=i-lp[i];
	buc[0][0]=1;
	for(int i=0,j=2;j<=n;j++){
		if(nxt[j])a[j]=a[nxt[j]];
		else {
			i=nxt[j-1];
			for(int k=0;k<26;k++)
			if(!buc[i][k]){a[j]=k;break;}
		}
		memcpy(buc[j-1],buc[nxt[j-1]],sizeof(buc[nxt[j-1]]));
		buc[j-1][a[j]]=1;
	}
	for(int i=1;i<=n;i++)putchar(a[i]+'a');
}
posted @ 2019-09-24 14:51  Stargazer_cykoi  阅读(88)  评论(0编辑  收藏  举报