bzoj 4974 字符串大师
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4974
题意:
给出一个字符串的前缀的每个位置的最短循环节,构造符合的字典序最小的字符串。
题解:
如果当前的i!=pre_i,就相当于已知循环节和循环的串求后面的某个位置,xjb取个模就可以知道了
如果当前是i==pre_i,可以考虑KMP的next数组构造,记录下哪些可以可以与前面的匹配从而构成循环节,删去这些字母找个最小的就可以了。
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f 3 using namespace std; 4 typedef long long ll; 5 const int mod=1e9+7; 6 const int maxn=1e5+100; 7 const double eps=1e-10; 8 int n,a[maxn]; 9 bool vis[30]; 10 char s[maxn]; 11 int main() { 12 #ifdef ac 13 freopen("in.txt" , "r" , stdin); 14 // freopen("out.txt" , "w" , stdout); 15 #endif 16 scanf("%d",&n); a[0]=0; 17 for(int i=1;i<=n;++i) scanf("%d",&a[i]); 18 s[1]='a'; char tmp='b'; 19 for(int i=2;i<=n;++i) { 20 if(i!=a[i]) s[i]=s[(i-1)%a[i]+1]; 21 else { 22 int tmp=i-1; 23 memset(vis,0,sizeof(vis)); 24 while(tmp!=a[tmp]) { 25 tmp=(tmp-1)%a[tmp]+1; 26 vis[s[tmp+1]-'a']=1; 27 } 28 for(int j=1;j<26;++j) { 29 if(!vis[j]) {s[i]=j+'a';break;} 30 } 31 } 32 } 33 s[n+1]=0; 34 printf("%s\n",s+1); 35 return 0; 36 }
沉迷于日日菜醒,不能自拔
posted on 2017-08-21 10:18 仰望咸鱼Orzzzz 阅读(690) 评论(0) 编辑 收藏 举报