• 字符串大师


    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 }


  • 相关阅读:
    jenkins初始化启动报错导致进入web页面无法安装插件
    redis5.0.7集群搭建
    搭建redis哨兵模式
    Linux服务器安装python3.6
    MySQL绿色版安装
    OSChina中远程GIT仓库同步探索
    Android坡度计
    利用ADB获取APP资源
    实现两台路由器无线桥接
    新体能评定软件开发总结(一)
  • 原文地址:https://www.cnblogs.com/cutepota/p/12560117.html
Copyright © 2020-2023  润新知