3790: 神奇项链
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 405 Solved: 200
[Submit][Status][Discuss]
Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。
Output
多行,每行一个答案表示最少需要使用第二个机器的次数。
Sample Input
abcdcba
abacada
abcdef
abacada
abcdef
Sample Output
0
2
5
2
5
HINT
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000
题意有bug,第二个机器拼的不一定是回文串
第二个机器好有意思哈,回文串还会是回文串性质并没有改变,只不过有重复一段而已
那么Manacher求出所有最长回文串,做区间覆盖就好啦....
我太愚蠢了Manacher又写错了i达成1
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1e5+5; int n; char s[N],str[N]; void iniStr(char *str,char *s){ for(int i=1;i<=n;i++) s[(i<<1)-1]='#',s[i<<1]=str[i]; s[0]='$';s[n<<1|1]='#'; } int r[N]; void Manacher(char *s,int n){ int p=0,a; for(int i=1;i<=n;i++){ r[i]=i<p?min(p-i+1,r[2*a-i]):1; while(s[i-r[i]]==s[i+r[i]]) r[i]++; if(i+r[i]-1>p) p=i+r[i]-1,a=i; } } struct Seq{ int l,r; bool operator <(const Seq &a) const{ return l<a.l||(l==a.l&&r>a.r); } }a[N]; void solve(){ n=n<<1; for(int i=1;i<=n;i++) a[i].l=i-r[i]+1,a[i].r=i+r[i]-1; sort(a+1,a+1+n); int now=a[1].r+1,ans=1,r,i=2; while(now<=n){ r=0; while(i<=n&&a[i].l<=now) r=max(r,a[i].r),i++; now=r+1; ans++; } printf("%d\n",ans-1); } int main(){ freopen("in","r",stdin); while(scanf("%s",str+1)!=EOF){ memset(r,0,sizeof(r)); memset(s,0,sizeof(s)); n=strlen(str+1); iniStr(str,s); Manacher(s,n<<1); solve(); } }