字符串大师

Description

一个串T是S的循环节,当且仅当存在正整数k,使得S是T^k(即T重复k次)的前缀,比如abcd是abcdabcdab的循环节
。给定一个长度为n的仅由小写字符构成的字符串S,请对于每个k(1<=k<=n),求出S长度为k的前缀的最短循环节的
长度per_i。字符串大师小Q觉得这个问题过于简单,于是花了一分钟将其AC了,他想检验你是否也是字符串大师。
小Q告诉你n以及per_1,per_2,...,per_n,请找到一个长度为n的小写字符串S,使得S能对应上per。

Input

第一行包含一个正整数n(1<=n<=100000),表示字符串的长度。
第二行包含n个正整数per_1,per_2,...per_n(1<=per_i<=i),表示每个前缀的最短循环节长度。
输入数据保证至少存在一组可行解。

Output

输出一行一个长度为n的小写字符串S,即某个满足条件的S。
若有多个可行的S,输出字典序最小的那一个。

Sample Input

5
1 2 2 2 5

Sample Output

ababb


sol:1~n位最短循环节的长度=n-next(n),那么next(n)=n-循环节长度。本题模拟数据如下:

10  //字串长度为10
1 1 3 4 4 4 7 7 7 7  //对于每一位截至的前缀,最小循环节长度

0 1 0 0 1 2 0 1 2 3 //根据n-循环节长度,求得每一位的next值

a  //字典序最小,第1位定为a。

a a  //next[2]=1,则说明第2位与第1位相等。

a a b  //next[3]=0,说明第3位与next[3-1]+1不等,即第3位与第2位不等,回退,第3位与next[2-1]+1位,即第1位,也不等,按顺序取到b。

a a b b //next[4]=0,说明第4位与next[4-1]+1不等,即第4位与第1位不等,按顺序取到b。

a a b b a  //第5位与第1位相等。

a a b b a a //第6位与第2位相等。

a a b b a a c //next[7]=0,说明与next[6-1]+1,即第3位不等,回退,与next[3-1]+1,即第2位也不等,回退,与next[2-1]+1,即第1位也不等,第7位按顺序取到c。

......

a a b b a a c a a b  //最后结果

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,nxt[100001];
 4 char s[100001];
 5 bool flag[26];
 6 int main() {
 7     scanf("%d",&n);
 8     for(int i=1;i<=n;i++) //求出真实的nxt数组 
 9     {
10         scanf("%d",nxt+i);
11         nxt[i]=i-nxt[i];
12     }
13     s[1]='a'; //第一个位置当然是放a 
14     for(int i=2;i<=n;i++)//一路扫过去 
15     {
16         if(nxt[i])//如果大于零,可直接算出当前这一位的字母是哪一个 
17         {
18             s[i]=s[nxt[i]];
19         }
20         else
21         {
22             //如果为0,则说明有些字母是不能取的 
23             int p=nxt[i-1]+1;//P代表,当前字符不能为字符串中第P个字符 
24             memset(flag,false,sizeof(flag));
25             flag[0]=true;//字母a已取过了 
26             while(p!=1)
27             {
28                 flag[s[p]-'a']=true;
29                 p=nxt[p-1]+1;
30             }
31             for(int j=0;j<26;j++) // 找出第一个能取的字符出来 
32             {
33                 if(!flag[j])
34                 {
35                     s[i]=j+'a';
36                     break;
37                 }
38             }
39         }
40     }
41     s[n+1]='';
42     printf("%s
",s+1);
43     return 0;
44 }


原文地址:https://www.cnblogs.com/cutepota/p/12560117.html