题目大意:
一个串T是S的循环节 当且仅当存在正整数k 使得S是T重复k次的前缀 比如abcd是abcdabcdab的循环节
给定一个长度为n的仅由小写字符构成的字符串S 请对于每个k(1<=k<=n) 求出S长度为k的前缀的最短循环节的长度per_i
已知per_1,per_2,...,per_n 请找到一个长度为n的小写字符串S 使得S能对应上per
思路:
若一个per i!=i 直接模一下在之前的里面找就行了
若不是 找到一些之前循环中出现的字符,这些字符如果出现在这一位会导致循环per改变
仿照next数组的思路 找出来 加上字典序最小的一个可用字符
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<queue> 8 #include<map> 9 #include<vector> 10 #define ll long long 11 #define inf 2147483611 12 #define MAXN 1000100 13 #define MOD 1000000 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 int n,a[MAXN],cnt,hsh[30],j; 23 char ans[MAXN]; 24 int main() 25 { 26 n=read(); 27 for(int i=1;i<=n;i++) a[i]=read(); 28 ans[1]='a'; 29 for(int i=2;i<=n;i++) 30 { 31 if(a[i]!=i) {ans[i]=ans[((i-1)%a[i])+1];continue;} 32 cnt++; 33 j=i-1; 34 while(a[j]!=j) 35 { 36 j=(j-1)%a[j]+1; 37 hsh[ans[j+1]-'a']=cnt; 38 } 39 for(int k=1;k<=26;k++) if(hsh[k]!=cnt) {ans[i]=(char) 'a'+k;break;} 40 } 41 for(int i=1;i<=n;i++) printf("%c",ans[i]); 42 }