zoukankan      html  css  js  c++  java
  • BZOJ4974 大视野1708月赛 字符串大师

    传送门

    题目大意

    给定一个字符串的每一个前缀的最短循环节长度,求符合要求的字典序最小的字符串。

    题解

    给定循环节最短长度就是给定了这个字符串$kmp$的$next$数组,即$X_i=i-next_i$,$X_i$表示给定的循环节长度。

    由于答案一定有解,考虑模拟构造一个这样的字符串,并模拟求它的$next$数组的过程。如果匹配到发现$i$从$j$处转移,那么就用$j$处的字母赋给$i$,否则就得到了$i,j$互不相同的条件,我们就得到了一个$i$不能取得字符集$S$,对$S$取$mex$即可。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 100020
    using namespace std;
    namespace IO{
    	const int BS=(1<<20); int Top=0;
    	char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[20]; const char *fin=OT+BS-1;
    	char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
    	void flush(){fwrite(OT,1,OS-OT,stdout);}
    	void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;}
    	void write(int x){
    		if(!x){Putchar('0');return;} if(x<0) x=-x,Putchar('-');
    		while(x) SS[++Top]=x%10,x/=10;
    		while(Top) Putchar(SS[Top]+'0'),--Top;
    	}
    	int read(){
    		int nm=0,fh=1; char cw=Getchar();
    		for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
    		for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
    		return nm*fh;
    	}
    }
    using namespace IO;
    int n,m,p[M],nxt[M]; char s[M]; bool G[M][26];
    int main(){
    	n=read(),s[1]='a',nxt[0]=-1,memset(G,true,sizeof(G));
    	for(int i=1;i<=n;i++) p[i]=read(),nxt[i]=i-p[i]; Putchar('a');
    	for(int i=2;i<=n;i++){
    		for(int j=nxt[i-1]+1;j>=0;j=nxt[j-1]+1){
    			if(!j){for(int k=0;k<26;k++) if(G[i][k]){s[i]=k+'a';break;}}
    			else if(nxt[i]==j) s[i]=s[j];
    			else{G[i][s[j]-'a']=false;continue;}break;
    		} Putchar(s[i]);
    	}Putchar('
    '),flush(); return 0;
    }
  • 相关阅读:
    栈——有效括号问题
    链表——判断是否有环,如果有,找到入口节点并返回(转自leetcode,个人留存)
    链表—判断是否有环
    链表—判断是否有环
    链表成对反转
    反转链表
    __attribute__机制
    linux write()
    错题本本-20180919
    C++ 11特性
  • 原文地址:https://www.cnblogs.com/OYJason/p/9824951.html
Copyright © 2011-2022 走看看