
4974: 字符串大师
发布日期:2021-05-06 23:47:47
浏览次数:20
分类:原创文章
本文共 1408 字,大约阅读时间需要 4 分钟。
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
我们可以观察到一个性质next[i]=i-p[i]
知道了这个就很好做了
对于p[i]!=i的情况,%一下就好了
否则,按next来跳,将每个到的位+1的字母标为不能选。。
最后选最小就好
CODE:
#include<cstdio>#include<cstring>const int N=100005;int n;int a[N];char ss[N];int f[N];int MOD (int x,int y){ if (x%y==0) return y; return x%y;}bool vis[27];void solve (){ ss[1]='a'; for (int u=2;u<=n;u++) { if (a[u]!=u) ss[u]=ss[MOD(u,a[u])]; else { memset(vis,false,sizeof(vis)); int j=f[u-1]; while (j!=-1) { vis[ss[j+1]-'a']=true; j=f[j]; } for (int i=0;i<=26;i++) if (vis[i]==false) { ss[u]=i+'a'; break; } } }}int main(){ f[0]=-1; scanf("%d",&n); for (int u=1;u<=n;u++) { scanf("%d",&a[u]); f[u]=u-a[u]; } solve(); for (int u=1;u<=n;u++) printf("%c",ss[u]); return 0;}
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2025年03月31日 16时09分57秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
云计算之路-阿里云上:2014年6月12日12点IIS请求到达量突降
2019-03-06
上周热点回顾(6.9-6.15)
2019-03-06
上周热点回顾(6.16-6.22)
2019-03-06
上周热点回顾(6.23-6.29)
2019-03-06
上周热点回顾(10.20-10.26)
2019-03-06
上周热点回顾(2.16-2.22)
2019-03-06
上周热点回顾(3.2-3.8)
2019-03-06
[网站公告]3月10日23:00-4:00阿里云SLB升级,会有4-8次连接闪断
2019-03-06
.NET跨平台之旅:借助ASP.NET 5 Beta5的新特性显示CLR与操作系统信息
2019-03-06
上周热点回顾(7.27-8.2)
2019-03-06
上周热点回顾(9.28-10.4)
2019-03-06
上周热点回顾(3.28-4.3)
2019-03-06
上周热点回顾(5.2-5.8)
2019-03-06
上周热点回顾(5.9-5.15)
2019-03-06
上周热点回顾(8.8-8.14)
2019-03-06
.NET跨平台之旅:将示例站点升级至 .NET Core 1.1 Preview 1
2019-03-06
上周热点回顾(1.16-1.22)
2019-03-06
上周热点回顾(1.23-1.29)
2019-03-06
上周热点回顾(3.20-3.26)
2019-03-06
上周热点回顾(4.24-4.30)
2019-03-06