• BZOJ4974 八月月赛 Problem D 字符串大师 KMP


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ4974 - 八月月赛 Problem D


    题意概括

      一个串T是S的循环节,当且仅当存在正整数k,使得S是T^k(即T重复k次)的前缀,比如abcd是abcdabcdab的循环节。给定一个长度为n的仅由小写字符构成的字符串S,请对于每个k(1<=k<=n),求出S长度为k的前缀的最短循环节的长度per_i。字符串大师小Q觉得这个问题过于简单,于是花了一分钟将其AC了,他想检验你是否也是字符串大师。小Q告诉你n以及per_1,per_2,...,per_n,请找到一个长度为n的小写字符串S,使得S能对应上per。


     题解

      

      详细操作见代码。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    using namespace std;
    const int N=100000+5;
    int n,Next[N],same[N],fa[N];
    vector <int> diff[N],d2[N];
    char s[N];
    int getf(int k){
    	return fa[k]==k?k:fa[k]=getf(fa[k]);
    }
    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++){
    		fa[i]=i;
    		diff[i].clear();
    		d2[i].clear();
    	}
    	for (int i=1,x;i<=n;i++){
    		scanf("%d",&x);
    		Next[i]=i-x;
    		if (i==1)
    			continue;
    		int k;
    		for (k=i-1;k>0;k=Next[k])
    			if (Next[k]+1==Next[i])
    				break;
    			else
    				diff[i].push_back(Next[k]+1),diff[Next[k]+1].push_back(i);
    		if (Next[i]>0){
    			same[i]=Next[k]+1;
    			fa[getf(i)]=getf(Next[k]+1);
    		}
    		else
    			same[i]=-1;
    	}
    	for (int i=1;i<=n;i++){
    		int f=getf(i);
    		for (int j=0;j<diff[i].size();j++)
    			d2[f].push_back(diff[i][j]);
    	}
    	s[1]='a';
    	for (int i=2;i<=n;i++){
    		if (same[i]!=-1){
    			s[i]=s[same[i]];
    			continue;
    		}
    		bool f[26];
    		memset(f,0,sizeof f);
    		int bh=getf(i);
    		for (int j=0;j<d2[bh].size();j++){
    			if (d2[bh][j]>=i)
    				continue;
    			f[s[d2[bh][j]]-'a']=1;
    		}
    		int j;
    		for (j=0;j<26;j++)
    			if (!f[j])
    				break;
    		s[i]=j+'a';
    	}
    	for (int i=1;i<=n;i++)
    		printf("%c",s[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    【题解】2020 年电子科技大学 ACMICPC 暑假前集训 数据结构
    【逆向】某触控板驱动分析过程
    SME 2019 ACM 题解
    数据结构 & 算法模板汇总
    VS2010win32下cocos2dx控制台打印的方法
    CDMA写码与鉴权(转载)
    mapxtreme开发小结2(c#)
    LONG GetWindowLong函数功能
    无边框的对话框的大小拖动实现
    YUV介绍
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ4974.html
Copyright © 2020-2023  润新知