题目大意
给出一个长度为n的字符串,求这个字符串的所有前缀的最小循环节,现在反过来,给出所有前缀的最小循环节,求字典序最小的字符串。 ( N ≤ 100000 ) (N\le100000) (N≤100000)
解题分析
最小循环节=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;
}