zoukankan      html  css  js  c++  java
  • 【思维题 kmp 构造】bzoj4974: [Lydsy1708月赛]字符串大师

    字符串思博题这一块还是有点薄弱啊。

    Description

    一个串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。

    Input

    第一行包含一个正整数n(1<=n<=100000),表示字符串的长度。
    第二行包含n个正整数per_1,per_2,...per_n(1<=per_i<=i),表示每个前缀的最短循环节长度。
    输入数据保证至少存在一组可行解。

    Output

    输出一行一个长度为n的小写字符串S,即某个满足条件的S。
    若有多个可行的S,输出字典序最小的那一个。

    Sample Input

    5
    1 2 2 2 5

    Sample Output

    ababb

    题目分析

    暴力dfs

    好吧考试时候暴力还是要保证写得又快又不挂的

    时间复杂度$O(26^n)$。但是这个上界非常松,我不知道怎样是紧一点的下界。

    暴力枚举

    因为一定有解,那么每一个位置都枚举一种颜色看一看是否合法。

    时间复杂度$n^2$。但是好像实际效率和dfs差了多少。

    kmp

    从枚举的思路顺着下去,算法的瓶颈在于找到一个最小的合法当前颜色。

    我们知道如果存在最小循环节,那么其长度为$i-fail[i]$。于是从问题反面来看,只需要找到当前位置所有不可能的颜色,剩下的最小颜色就是其答案。那么求这个反面就相当于找$i$位置对应的所有合法的最小循环节。

    所以,在这颗抽象的fail树上向前跳就可以得到答案。

    还有一个处理的细节,就是$'a'$的特判。注意到$'a'$只会出现在$a[i]!=i(i!=1)$的位置。所以对于$a[i]==i$的位置,是不可能为$'a'$的,那么这里枚举答案时就要从$'b'$开始。

    #include<bits/stdc++.h>
    const int maxn = 100035;
    
    bool vis[31];
    int n,a[maxn],t[maxn];
    
    int read()
    {
    	char ch = getchar();
    	int num = 0;
    	for (; !isdigit(ch); ch=getchar());
    	for (; isdigit(ch); ch=getchar())
    		num = (num<<1)+(num<<3)+ch-48;
    	return num;
    }
    int main()
    {
    	freopen("string.in","r",stdin); 
    	freopen("string.out","w",stdout); 
    	n = read();
    	for (int i=1; i<=n; i++) a[i] = read();
    	for (int i=2; i<=n; i++)
    	{
    		if (a[i]!=i) t[i] = t[(i-1)%a[i]+1];
    		else{
    			memset(vis, 0, sizeof vis);
    			int j = i-1;
    			while (j!=a[j])
    				j = (j-1)%a[j]+1, vis[t[j+1]] = 1;
    			for (int k=1; k<26; k++)
    				if (!vis[k]){
    					t[i] = k;
    					break;
    				}
    		}
    	}
    	for (int i=1; i<=n; i++) putchar(t[i]+'a');
    	return 0;
    }
    

    END

  • 相关阅读:
    pika的阻塞式使用
    使用 Nuget安装DLL
    StackExchange.Redis的使用
    MongoDB 学习笔记(9)--- Limit与Skip方法
    MongoDB 学习笔记(8)---$type 操作符
    MongoDB学习笔记(7)--- 条件操作符
    MongoDB学习笔记(6)--find
    阿里巴巴Java开发规范手册
    python获取当前文件路径
    断网环境下利用pip安装Python离线安装包
  • 原文地址:https://www.cnblogs.com/antiquality/p/9806707.html
Copyright © 2011-2022 走看看