BZOJ3790: 神奇项链
2014-12-17 17:24
441 查看
3790: 神奇项链
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 79 Solved: 40
[Submit][Status]
Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H
购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和
一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或
abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。Output
多行,每行一个答案表示最少需要使用第二个机器的次数。Sample Input
abcdcbaabacada
abcdef
Sample Output
02
5
HINT
每个测试数据,输入不超过 5行每行的字符串长度小于等于 50000
题解:
我想呵呵。。。
我是这样想得,我们先manacher一遍,令f[i]表示打出1--i的最小花费
然后可以O(n)求出以每个点结尾的最长回文子串,不妨设最远扩展到x,
然后就可以用min(f[j])(x-1<=j<=i-1) +1来更新f[i]
就可以线段树搞了。
代码:
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<queue> #include<string> #define inf 1000000000 #define maxn 500000+5 #define maxm 20000000+5 #define eps 1e-10 #define ll long long #define pa pair<int,int> #define for0(i,n) for(int i=0;i<=(n);i++) #define for1(i,n) for(int i=1;i<=(n);i++) #define for2(i,x,y) for(int i=(x);i<=(y);i++) #define for3(i,x,y) for(int i=(x);i>=(y);i--) #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} return x*f; } int n,m,a[maxn],f[maxn],p[maxn]; char s[maxn]; struct seg{int k,l,r,mi;}t[4*maxn]; inline void build(int k,int l,int r) { t[k].l=l;t[k].r=r;int mid=(l+r)>>1;t[k].mi=inf; if(l==r){if(!l)t[k].mi=-1;return;} build(k<<1,l,mid);build(k<<1|1,mid+1,r); } inline void pushup(int k) { t[k].mi=min(t[k<<1].mi,t[k<<1|1].mi); } inline void change(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if(l==r){t[k].mi=min(t[k].mi,y);return;} if(x<=mid)change(k<<1,x,y);else change(k<<1|1,x,y); pushup(k); } inline int query(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if(l==x&&r==y)return t[k].mi; if(y<=mid)return query(k<<1,x,y); else if(x>mid)return query(k<<1|1,x,y); else return min(query(k<<1,x,mid),query(k<<1|1,mid+1,y)); } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); while(scanf("%s",s)!=EOF) { n=strlen(s); build(1,0,n); for1(i,n)a[i<<1]=s[i-1]; m=n;n=2*n+1; int id=0,mx=0; for1(i,n) { if(mx>i)p[i]=min(p[2*id-i],mx-i); while(i-p[i]-1>0&&i+p[i]+1<=n&&a[i-p[i]-1]==a[i+p[i]+1])p[i]++; if(i+p[i]>mx)mx=i+p[i],id=i; } int now=0; for1(i,n)if(i+p[i]>now) { for2(j,now+1,i+p[i])f[j]=2*i-j; now=i+p[i]; } for1(i,m)change(1,i,query(1,max(0,(f[i<<1]>>1)-1),i-1)+1); printf("%d\n",query(1,m,m)); memset(a,0,sizeof(a)); memset(s,0,sizeof(s)); memset(p,0,sizeof(p)); memset(f,0,sizeof(f)); } return 0; }
View Code
刚开始装逼用gets结果WA了好几发感觉人生无望,这种题都A不了,就颓了一节课T_T
UPD:orzky的题解http://blog.csdn.net/iamzky/article/details/41852799
相关文章推荐
- BZOJ 3790 神奇项链 (Manacher 贪心)
- BZOJ 3790: 神奇项链 manacher
- BZOJ 3790: 神奇项链
- BZOJ3790 : 神奇项链
- bzoj 3790: 神奇项链 manachar+dp+树状数组
- 【BZOJ3790】神奇项链
- [BZOJ3790]神奇项链(manacher+贪心)
- 【bzoj3790】神奇项链——manacher+贪心
- bzoj3790 神奇项链
- 【BZOJ】3790 神奇项链
- 【BZOJ3790】神奇项链(manacher,树状数组)
- 【BZOJ3790】神奇项链 Manacher+贪心
- bzoj 3790 神奇项链(Manacher,DP+BIT | 贪心)
- BZOJ_3790_神奇项链_manacher+贪心
- 【bzoj3790】【神奇项链】【manacher+dp+树状数组】
- [BZOJ]3790 神奇项链 Manacher+树状数组
- [BZOJ3790] 神奇项链
- manacher(马拉车)算法详解+例题一道【bzoj3790】【神奇项链】
- BZOJ 3790 神奇项链(manacher+DP+树状数组)
- BZOJ3790 神奇项链 解题报告【字符串】【Manacher】【树状数组】【数据结构优化DP】