bzoj 4974 [Lydsy1708月赛]字符串大师 KMP 最小循环元 构造

LINK:字符串大师

给出一个字符串的每个前缀的最小循环元 还原字典序最小的原字符串。

一个比较显然的结论 或者说 学过KMP的都知道 对于每个前缀i求出nex数组后 那么i-nex[i]为最小循环元。

这道题择则是给出每个前缀的最小循环元 由于题目中保证有解

我们可以推得 nex[i]=i-循环元长度。由于存在解 说明对于nex[i]!=0的时候直接到使用nex[i]的字符即可。

当nex[i]==0时我们可以调nex 把不合法的字符都给标记一下 然后重新选择字符即可。

注意边界问题 nex[0]=-1这样好写一点。

const int MAXN=100010;
int n;
int w[MAXN],b[MAXN],vis[26];
char a[MAXN];
int main()
{
	freopen("1.in","r",stdin);
	get(n);b[0]=-1;
	rep(1,n,i)get(w[i]);
	a[1]='a';
	rep(2,n,i)
	{
		b[i]=i-w[i];
		if(!b[i])
		{
			rep(0,25,j)vis[j]=0;
			int cc=b[i-1];
			while(cc!=-1)
			{
				vis[a[cc+1]-'a']=1;
				cc=b[cc];
			}
			rep(0,25,j)if(!vis[j]){a[i]=j+'a';break;}
		}
		else a[i]=a[b[i]];
	}
	printf("%s",a+1);
	return 0;
}
posted @ 2020-04-10 21:05  chdy  阅读(116)  评论(0编辑  收藏  举报