zoukankan      html  css  js  c++  java
  • [BZOJ4947] 字符串大师

    4974: [Lydsy1708月赛]字符串大师

    Time Limit: 1 Sec  Memory Limit: 256 MB
    Submit: 739  Solved: 358
    [Submit][Status][Discuss]

    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

    HINT

    Source

     

     
    题解:
    我们由最短循环节=i-nxt[i],可以求出每个nxt。
    然后贪心地求出答案。
    每一位如果它nxt不为0,直接ans[i]=ans[xt[i]];
    如果它等于0,那么考虑kmp的过程,沿着nxt[i-1]一直往前跑找到的每一个j,ans[j+1]都不能是现在的ans[i],然后每次取未出现过的字典序最小的字母即可;
     

     
    Code:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <map>
     4 using namespace std;
     5 
     6 int n;
     7 int nxt[100010];
     8 char ans[100010];
     9 
    10 int main()
    11 {
    12     scanf("%d", &n);
    13     for (register int i = 1 ; i <= n ; i ++)
    14     {
    15         int x;
    16         scanf("%d", &x);
    17         nxt[i] = i - x;
    18     }
    19     nxt[0] = -1;
    20     ans[1] = 'a';
    21     
    22     for (register int i = 2 ; i <= n ; i ++)
    23     {
    24         if (nxt[i] > 0) ans[i] = ans[nxt[i]];
    25         else
    26         {
    27             map <char, bool> mp;
    28             mp.clear();
    29             int las = nxt[i-1] + 1;
    30             while (las)
    31             {
    32                 mp[ans[las]] = 1;
    33                 las = nxt[las-1] + 1;
    34             }
    35             for (register int j = 'a' ; j <= 'z' ; j ++)
    36             {
    37                 if (!mp[j]) {ans[i] = j;break;}
    38             }
    39         }
    40     }
    41     for (register int i = 1 ; i <= n ; i ++) printf("%c", ans[i]);
    42     return 0;
    43 }
     
  • 相关阅读:
    Socket基础一
    MyBatisPlus【目录】
    MyBatis(十一)扩展:自定义类型处理器
    MyBatis(十一)扩展:批量操作
    MyBatis(十一)扩展:存储过程
    MyBatis(十一)扩展:分页插件PageHelper
    MyBatis(十)插件 4
    09月07日总结
    09月06日总结
    09月03日总结
  • 原文地址:https://www.cnblogs.com/BriMon/p/9180015.html
Copyright © 2011-2022 走看看