BZOJ 3790 神奇项链 Hash+二分+树状数组

来源:互联网 发布:淘宝店铺会员制度 编辑:程序博客网 时间:2024/05/21 09:05

题目大意:给定一个串,问这个串最少可以由回文串拼接多少次而成(拼接可以重叠)

首先将每两个字符之间插入占位符,然后Hash+二分搞出所有极大回文串(可以用manacher,我不会)

问题转化成了给定一些区间,求最少的能覆盖整个数轴的区间

将所有区间按照某一端点排序 然后上树状数组即可

回头还是去学学manacher吧。。。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 100100#define BASE 131using namespace std;typedef unsigned long long ll;struct Interval{int x,y;bool operator < (const Interval &Y) const{return x < Y.x ;}}intervals[M];int n;char s[M],_s[M<<1];ll sum1[M<<1],sum2[M<<1],power[M<<1];namespace BIT{int c[M];inline void Update(int x,int y){for(;x;x-=x&-x)c[x]=min(c[x],y);}inline int Get_Ans(int x){int re=0x3f3f3f3f;for(;x<=n;x+=x&-x)re=min(re,c[x]);return re;}}void Initialize(){memset(_s,0,sizeof _s);memset(sum1,0,sizeof sum1);memset(sum2,0,sizeof sum2);memset(BIT::c,0x3f,sizeof BIT::c);}bool Judge(int x,int len){int l=x-len+1;int r=x+len-1;return  sum1[r]-sum1[l-1]*power[r-l+1]==sum2[l]-sum2[r+1]*power[r-l+1];}int Bisection(int x){int l=1,r=min(x,n-x+1);while(l+1<r){int mid=l+r>>1;if( Judge(x,mid) )l=mid;elser=mid;}if( Judge(x,r) )return r;return l;}int main(){int i;for(i=1,power[0]=1;i<M<<1;i++)power[i]=power[i-1]*BASE;while(~scanf("%s",s+1) ){Initialize();n=strlen(s+1);for(i=1;i<=n;i++){_s[i<<1]=s[i];_s[i+i-1]='#';}_s[n=n+n+1]='#';for(i=1;i<=n;i++)sum1[i]=sum1[i-1]*BASE+_s[i];for(i=n;i;i--)sum2[i]=sum2[i+1]*BASE+_s[i];for(i=1;i<=n;i++){int temp=Bisection(i);intervals[i].x=i-temp+1;intervals[i].y=i+temp-1;}sort(intervals+1,intervals+n+1);BIT::Update(1,-1);for(i=1;i<=n;i++){int temp=BIT::Get_Ans(intervals[i].x);BIT::Update(intervals[i].y,temp+1);}printf("%d\n", BIT::Get_Ans(n) );}}


0 0
原创粉丝点击