题目可转换为已知一个串kmp之后的nxt数组,求字典序最小的原串。
已知第i位结尾的串循环节长度位x,那么nxt[i]=i-x;
当nxt不为0时,s[i]=s[nxt[i]];
nxt为0时,那么考虑kmp的过程,沿着nxt[i-1]一直往前跑找到的每一个j,s[j+1]都不能是现在的s[i],那么在一路求nxt的过程中就从前往后递推用一个二进制串表示一路的nxt的后一位出现过的字母,然后每次取未出现过的字典序最小的字母即可;
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=100007;
typedef long long LL;
using namespace std;
int n,nxt[N],vis[N];
char s[N];
template<typename T> void read(T &x) {
T f=1; x=0; char ch=getchar();
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
if(ch==‘-‘) f=-1,ch=getchar();
for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n);
for(int i=1;i<=n;i++) {
read(nxt[i]);
nxt[i]=i-nxt[i];
}
s[0]=‘a‘; vis[1]=1;
for(int i=2;i<=n;i++) {
if(nxt[i]!=0) s[i-1]=s[nxt[i]-1];
else {
for(int j=0;j<26;j++)
if(!(vis[i-1]&(1<<j))) {
s[i-1]=‘a‘+j;
break;
}
}
vis[i]=(vis[nxt[i]]|(1<<(s[nxt[i]]-‘a‘)));
}
puts(s);
return 0;
}