zoukankan      html  css  js  c++  java
  • 【BZOJ3325】[Scoi2013]密码 Manacher

    【BZOJ3325】[Scoi2013]密码

    Description

    Fish是一条生活在海里的鱼。有一天他很无聊,就到处去寻宝。他找到了位于海底深处的宫殿,但是一扇带有密码锁的大门却阻止了他的前进。通过翻阅古籍,Fish 得知了这个密码的相关信息:
    1. 该密码的长度为N。
    2. 密码仅含小写字母。
    3. 以每一个字符为中心的最长回文串长度。
    4. 以每两个相邻字符的间隙为中心的最长回文串长度。
    很快Fish 发现可能有无数种满足条件的密码。经过分析,他觉得这些密码中字典序最小的一个最有可能是答案,你能帮他找到这个密码么?
    注意:对于两个串A和B,如果它们的前i个字符都相同,而A的第i+1个字符比B的第i+1个字符小,那么认为是则称密码A 的字典序小于密码B 的字典序,例如字符串abc 字典序小于字符串acb。如果密码A的字典序比其他所有满足条件的密码的字典序都小,则密码A是这些密码中字典序最小的一个。

    Input

    输入由三行组成。
    第一行仅含一个整数N,表示密码的长度。
    第二行包含N 个整数,表示以每个字符为中心的最长回文串长度。
    第三行包含N - 1 个整数,表示每两个相邻字符的间隙为中心的最长回文串长度。
    对于20% 的数据,1 <= n <= 100。
    另有30% 的数据,1 <= n <= 1000。
    最后50% 的数据,1 <= n <= 10^5。

    Output

    输出仅一行。输出满足条件的最小字典序密码。古籍中的信息是一定正确的,故一定存在满足条件的密码。

    Sample Input

    Sample #1
    3
    1 1 1
    0 0
    Sample #2
    3
    1 3 1
    0 0
    Sample #3
    3
    1 3 1
    2 2

    Sample Output

    Sample #1
    abc
    Sample #2
    aba
    Sample #3
    aaa

    题解:我们模拟Manacher的过程,Manacher的时候是当str[..]=str[..]时,rl[i]++,那么我们已知了rl,如果rl比当前值大了,则说明str[..]=str[..],否则str[..]!=str[..]。

    相等的条件比较好判断,那不等的条件呢?用f[i][j]表示i字符能不能取j,那么如果i字符没有与...相等的条件,就让它等于i可以取的最小字符即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=200010;
    char str[maxn];
    int n,mx,pos;
    int rl[maxn],f[maxn][26];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd();
    	int i,j;
    	for(i=1;i<=n;i++)	rl[i*2-1]=rd()+1;
    	for(i=1;i<=n-1;i++)	rl[i*2]=rd()+1;
    	n<<=1,str[1]='a',str[0]='*',rl[0]=1;
    	for(i=0,mx=-1;i<=n;i++)
    	{
    		if(!(i&1))	str[i]='*';
    		else
    		{
    			if(str[i]<'a')
    			{
    				for(j=0;j<26;j++)	if(!f[i][j])	break;
    				str[i]='a'+j;
    			}
    		}
    		if(mx>i)	j=min(mx-i+1,rl[2*pos-i]);
    		else	j=1;
    		for(j--;j<rl[i];j++)	str[i+j]=str[i-j];
    		if(rl[i]<=i)	f[i+rl[i]][str[i-rl[i]]-'a']=1;
    		if(mx<i+rl[i]-1)	mx=i+rl[i]-1,pos=i;
    	}
    	for(i=1;i<n;i+=2)	printf("%c",str[i]);
    	return 0;
    }
  • 相关阅读:
    关于本Blog无法进行评论问题的说明
    Apusic Operamasks例子部署过程
    JVM启动参数(转)
    20070724中间件产品培训方式总结
    写Blog的意义
    磁碟機讀取光碟片時遇故障7/9
    .aspx沒有語言擴充功能8/14
    水晶報表公式的dateadd及cstr應用7/11
    中毒了:Trojar6/26
    學位英語考試通過啦8/28
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7560180.html
Copyright © 2011-2022 走看看