bzoj3790 神奇项链
Posted kafuuchino
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3790 神奇项链相关的知识,希望对你有一定的参考价值。
Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。
Output
多行,每行一个答案表示最少需要使用第二个机器的次数。
Sample Input
abcdcba
abacada
abcdef
Sample Output
0
2
5
Hint
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000
manacher+贪心
manacher:一种线性时间求回文串长度的算法(右转Baidu)
用manacher处理出以某个点开始的最长回文串长度,问题就转变成区间覆盖问题。
用贪心跑一遍即可。
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> using namespace std; template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;} template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;} char a[1000005],b[1000005]; int p[1000005],f[1000005]; int main(){ while(scanf("%s",a)!=EOF){ memset(f,0,sizeof(f)); int len=strlen(a),n=0,id=0,mx=-1,last,mxd,ans=0; for(int i=0;i<len;++i) b[n++]=‘#‘,b[n++]=a[i]; b[n++]=‘#‘; for(int i=0;i<n;++i){ if(i<mx) p[i]=min(p[id*2-i],mx-i+1); else p[i]=1; while(i-p[i]>=0&&i+p[i]<n&&b[i-p[i]]==b[i+p[i]]) ++p[i]; if(i+p[i]-1>mx) mx=i+p[i]-1,id=i; f[i-p[i]+1]=i+p[i]-1; //处理出从点i-p[i]+1开始的最长回文串长度 }last=mxd=f[0]+2; for(int i=0;i<n;i+=2){ //贪心 if(i==last) last=mxd,++ans; mxd=max(mxd,f[i]+2); }printf("%d ",ans); }return 0; }
以上是关于bzoj3790 神奇项链的主要内容,如果未能解决你的问题,请参考以下文章