zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    写在寒假
    Docker安装Redis(两种方式)
    JVM类加载机制
    RabbitMQ学习
    MySQL索引详解
    Java内存区域
    Window10下的Docker Desktop安装(保姆级教程)
    JVM垃圾回收
    力扣Hot100(目前进度89/100)
    C# 发送邮件实例
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8185648.html
Copyright © 2011-2022 走看看