[KMP]BZOJ 4974 [Lydsy1708月赛]字符串大师 题解

题目大意

给出一个长度为n的字符串,求这个字符串的所有前缀的最小循环节,现在反过来,给出所有前缀的最小循环节,求字典序最小的字符串。 ( N ≤ 100000 ) (N\le100000) (N100000)

解题分析

最小循环节=i-nxt[i]

那么可以求出nxt数组。

求出来了又如何?

如果Nxt[i]已知,注意nxt[i]的定义是s[1…nxt[i]]=s[i-nxt[i]+1…n],那么明显s[i]=s[nxt[i]]

但如果nxt[i]=0,那怎么办?

注意到字符串只由小写字母构成,也就是最多26个元素,那么可以1个1个试试看,代入用前面的nxt数组验证。

然后好了。

示例代码

题目传送门

#include<cstdio>
#include<cstring>
using namespace std;
int n,tot,nxt[100005];
char s[100005];
int main()
{
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	scanf("%d",&n);
	for (int i=1,x;i<=n;i++){
		scanf("%d",&x); nxt[i]=i-x;
		if (i==1) {s[1]='a'; continue;}
		if (nxt[i]) s[i]=s[nxt[i]]; else{
			for (int z=0,j;z<26;z++){
				s[i]='a'+z; j=nxt[i-1];
				while (j&&s[j+1]!=s[i]) j=nxt[j];
				if (s[j+1]!=s[i]&&!j) break;
			}
		}
	}
	for (int i=1;i<=n;i++) putchar(s[i]);
	return 0;
}
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/try__jhf/article/details/83151386
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞