bzoj4974 [Lydsy1708月赛]字符串大师

Description

一个串 \(T\)\(S\) 的循环节,当且仅当存在正整数 \(k\) ,使得 \(S\)\(T^k\) (即 \(T\) 重复 \(k\) 次)的前缀,比如 \(\mathrm{abcd}\)\(\mathrm{abcdabcdab}\) 的循环节。给定一个长度为 \(n\) 的仅由小写字符构成的字符串 \(S\) ,请对于每个 \(k(1\le k\le n)\) ,求出 \(S\) 长度为 \(k\) 的前缀的最短循环节的长度 \(per_i\) 。字符串大师小 \(\mathrm{Q}\) 觉得这个问题过于简单,于是花了一分钟将其 \(\mathrm{AC}\) 了,他想检验你是否也是字符串大师。

\(\mathrm{Q}\) 告诉你 \(n\) 以及 \(per_1,per_2,\cdots ,per_n\) ,请找到一个长度为 \(n\) 的小写字符串 \(S\) ,使得 \(S\) 能对应上 \(per\)

Input

第一行包含一个正整数 \(n(1\le n\le 100000)\) ,表示字符串的长度。

第二行包含 \(n\) 个正整数 \(per_1,per_2,...per_n(1\le per_i\le i)\) ,表示每个前缀的最短循环节长度。

输入数据保证至少存在一组可行解。

Output

输出一行一个长度为 \(n\) 的小写字符串 \(S\) ,即某个满足条件的 \(S\)

若有多个可行的 \(S\) ,输出字典序最小的那一个。

Sample

Sample Input

5
1 2 2 2 5

Sample Output

ababb

Solution

首先有一个结论, \(pre[i]=i-next[i]\) 。所以这道题可以转化为已知 \(^*next\) 求原字符串。

我们来想想 \(\mathrm{kmp}\) 的过程。

void get_next() {
    int t1 = 0, t2 = next[0] = -1;
    while(t1 < len2)
        if(t2 == -1 || s2[t1] == s2[t2]) next[++t1] = ++t2;
        else t2 = next[t2];
}

所以我们就得到了一堆相等和不等关系,随便做就可以了。

#include<bits/stdc++.h>
using namespace std;

#define N 100001

inline int read() {
    int x = 0; char ch = getchar(); while (!isdigit(ch))  ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x;
}

char s[N];
int n, nxt[N];
bool f[N][27];

int main() {
    n = read();
    for (int i = 1; i <= n; i++) nxt[i] = i - read();
    int i = 0, j = nxt[0] = -1, k;
    while (i < n) {
        if (nxt[i + 1] == j + 1) {
            if (j ^ -1) s[i] = s[j];
            else {
                for (k = 0; k < 26; k++) if (!f[i][k]) break;
                s[i] = 'a' + k;
            }
            i++, j++;
        }
        else f[i][s[j] - 'a'] = 1, j = nxt[j];
    }
    printf("%s", s);
    return 0;
}

转载于:https://www.cnblogs.com/aziint/p/8643574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值