码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-03 22:42:50      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:数组   view   isp   pen   pos   img   deb   close   play   

传送门

题目可转换为已知一个串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八月月赛]字符串大师

标签:数组   view   isp   pen   pos   img   deb   close   play   

原文地址:https://www.cnblogs.com/Achenchen/p/8185648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!