bzoj4974: [Lydsy八月月赛]字符串大师

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4974: [Lydsy八月月赛]字符串大师相关的知识,希望对你有一定的参考价值。

传送门

题目可转换为已知一个串kmp之后的nxt数组,求字典序最小的原串。

已知第i位结尾的串循环节长度位x,那么nxt[i]=i-x;

当nxt不为0时,s[i]=s[nxt[i]];

nxt为0时,那么考虑kmp的过程,沿着nxt[i-1]一直往前跑找到的每一个j,s[j+1]都不能是现在的s[i],那么在一路求nxt的过程中就从前往后递推用一个二进制串表示一路的nxt的后一位出现过的字母,然后每次取未出现过的字典序最小的字母即可;

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=100007;
typedef long long LL;
using namespace std;
int n,nxt[N],vis[N];
char s[N];

template<typename T> void read(T &x) {
    T f=1; x=0; char ch=getchar();
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
}

int main() {
#ifdef DEBUG
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    read(n);
    for(int i=1;i<=n;i++) {
        read(nxt[i]);
        nxt[i]=i-nxt[i];
    }
    s[0]=a; vis[1]=1;
    for(int i=2;i<=n;i++) {
        if(nxt[i]!=0) s[i-1]=s[nxt[i]-1];
        else {
            for(int j=0;j<26;j++) 
                if(!(vis[i-1]&(1<<j))) {
                    s[i-1]=a+j;
                    break;
                }
        }
        vis[i]=(vis[nxt[i]]|(1<<(s[nxt[i]]-a)));
    }
    puts(s);
    return 0;
}
View Code

 

以上是关于bzoj4974: [Lydsy八月月赛]字符串大师的主要内容,如果未能解决你的问题,请参考以下文章

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

BZOJ5073[Lydsy十月月赛]小A的咒语 DP

bzoj 5091: [Lydsy0711月赛]摘苹果

[Bzoj5359][Lydsy1805月赛]寻宝游戏(dp)

BZOJ4952lydsy七月月赛 E 二分答案

bzoj 4921: [Lydsy六月月赛]互质序列