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 }
View Code

 

posted on 2017-08-21 10:18  仰望咸鱼Orzzzz  阅读(687)  评论(0编辑  收藏  举报

导航