首页 > 代码库 > bzoj3790 神奇项链

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第一题啊
这是一个O(n)的找回文串的算法
首先找出以每一位为中心的最长回文子串的区间,问题变成取最少的区间完全覆盖整个区间
排个序贪心就好了。显然是相同个数的区间尽量凑出右边界尽可能大的更优
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<deque>#include<set>#include<map>#include<ctime>#define LL long long#define inf 0x7ffffff#define pa pair<int,int>#define pi 3.1415926535897932384626433832795028841971using namespace std;inline LL read(){    LL x=0,f=1;char ch=getchar();    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}    return x*f;}inline void write(LL a){	if (a<0){printf("-");a=-a;}	if (a>=10)write(a/10);	putchar(a%10+‘0‘);}inline void writeln(LL a){write(a);printf("\n");}int len,cnt,tot,now,ans;char ch[100010],s[100010];int p[100010];struct srt{int l,r;}a[100010];bool operator <(srt a,srt b){return a.l<b.l||a.l==b.l&&a.r<b.r;}inline void manacher(){		cnt=tot=0;int mx=0,id=0;	for (int i=1;i<=len;i++)	{		s[++cnt]=‘#‘;		s[++cnt]=ch[i];	}	s[++cnt]=‘#‘;	s[0]=‘$‘;	for (int i=2;i<cnt;i++)	{		if (p[id]+id>i)p[i]=min(p[2*id-i],p[id]-(i-id));		else p[i]=1;		while (s[i+p[i]]==s[i-p[i]])p[i]++;		if (p[i]+i>p[id]+id)id=i;	}	memset(a,0,sizeof(a));	for (int i=1;i<=cnt;i++)	{		int res=p[i]-1;		int l=i-res,r=i+res;		if (l%2)l++;if (r%2)r--;		l/=2;r/=2;		if (l>r)continue;		a[++tot].l=l;		a[tot].r=r;	}}inline void work(){	len=strlen(ch+1);	manacher();	sort(a+1,a+tot+1);	now=ans=0;int i=1;	while (now!=len)	{		int to=-1;		while (a[i].l<=now+1&&i<=tot)			to=max(to,a[i].r),i++;		now=to;ans++;	}	printf("%d\n",ans-1);}int main(){	while (~scanf("%s",ch+1))work();}

  

bzoj3790 神奇项链