• 【BZOJ3790】神奇项链 Manacher+贪心


    【BZOJ3790】神奇项链

    Description

    母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
    母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。 

    Input

    输入数据有多行,每行一个字符串,表示目标项链的样式。 

    Output

    多行,每行一个答案表示最少需要使用第二个机器的次数。 

    Sample Input

    abcdcba
    abacada
    abcdef

    Sample Output

    0
    2
    5

    HINT

    每个测试数据,输入不超过 5行 
    每行的字符串长度小于等于 50000 

    题解:我们沿用最长双回文串那题里的做法,先在Manacher的同时求出rs[i],代表以i开头的最长回文串的结尾位置(上一题求的是长度,但都差不多)

    然后根据贪心的思想,我们一定是将一些极长回文子串连接起来组成原串(极长回文子串,意思是两边不能再同时延长的回文子串),当然中间可能有重叠部分,然后这就变成了一个用最少的线段来覆盖整个区间的问题,依旧是贪心,始终取右端点最右的线段就好了,时间复杂度O(n)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    char s1[500010],str[1000010];
    using namespace std;
    int n,len,mx,pos,last,maxx,ans;
    int rl[1000010],rs[1000010];
    void work()
    {
    	len=strlen(s1),n=0;
    	int i,j,a;
    	for(i=0;i<len;i++)	str[n++]='*',str[n++]=s1[i];
    	str[n++]='*';
    	memset(rs,0,sizeof(rs));
    	for(mx=-1,i=0;i<n;i++)
    	{
    		if(mx>i)	rl[i]=min(mx-i+1,rl[2*pos-i]);
    		else	rl[i]=1;
    		for(;i+rl[i]<n&&rl[i]<=i&&str[i+rl[i]]==str[i-rl[i]];rl[i]++);
    		if(mx<i+rl[i]-1)	mx=i+rl[i]-1,pos=i;
    		rs[i-rl[i]+1]=i+rl[i]-1;
    	}
    	ans=0,last=maxx=rs[0]+2;
    	for(i=0;i<n;i+=2)
    	{
    		if(i==last)	last=maxx,ans++;
    		maxx=max(maxx,rs[i]+2);
    	}
    	printf("%d
    ",ans);
    	return ;
    }
    int main()
    {
    	while(scanf("%s",s1)!=EOF)	work();
    	return 0;
    }
  • 相关阅读:
    python练习册 0002随机生成验证
    女生应该找什么样的男生
    博弈论 尼姆博弈,人生第一道博弈纪念一下
    博弈论版版
    博弈论
    STL用法大全
    据说是Flord算法
    20190716-T3-奇袭
    20190716-T1-礼物
    20190716-被水题淹没
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6803000.html
Copyright © 2020-2023  润新知