BZOJ2462: [BeiJing2011]矩阵模板 二维Hash
BZOJ3791: 作业 dp

BZOJ3790: 神奇项链 Manacher+线段树优化dp

shinbokuow posted @ Dec 16, 2014 11:18:51 PM in BZOJ with tags DP Manacher , 1533 阅读

首先令\(f_i\)表示前\(i\)个字符最少能被拆分为几个回文串,很显然能够列出转移方程:

\[f_{i}=min\{f_{j}+1\}(i-len[i]\leq{j}<i)\]

其中\(len[i]\)表示以位置\(i\)为结尾的最长回文串长度。

于是我们可以利用Manacher算法或者hash预处理出\(len\)数组,随后用线段树优化dp即可。时间复杂度\(O(nlogn)\).

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
 
#define INF 1<<30
 
#define N 50010
char s[N],work[N<<1];
 
struct SegmentTree{
    int Min[262144],M;
    inline void Init(int _siz){
        for(M=1;M<(_siz+2);M<<=1);
        memset(Min,0x3f,sizeof Min);
    }
    inline void Modify(int ins,int _v){
        for(Min[ins+=M]=_v,ins>>=1;ins;ins>>=1)Min[ins]=std::min(Min[ins<<1],Min[ins<<1^1]);
    }
    inline int Query(int tl,int tr){
        int res=INF;
        for(tl+=M-1,tr+=M+1;tl^tr^1;tl>>=1,tr>>=1){
            if(~tl&1)res=std::min(res,Min[tl^1]);
            if(tr&1)res=std::min(res,Min[tr^1]);
        }return res;
    }
}Seg;
 
int left[N],p[N<<1],f[N],g[N];
int main(){
    #ifndef ONLINE_JUDGE
    freopen("tt.in","r",stdin);
    #endif
 
    register int i,j;
    while(scanf("%s",s+1)!=EOF){
        int len=strlen(s+1);
 
        for(i=1;i<=len;++i){
            work[2*i-1]=s[i];
            work[2*i]='$';
        }work[len*=2]='@';
 
        memset(p,0,sizeof p);
        int ins(0),Maxid(0);
        for(i=1;i<=len;++i){
            if(Maxid>i)p[i]=std::min(p[2*ins-i],Maxid-i+1);
            while(work[i+p[i]]==work[i-p[i]])++p[i];
            if(i+p[i]-1>Maxid){
                for(j=Maxid+1;j<=i+p[i]-1;++j)left[j]=i;
                Maxid=i+p[i]-1,ins=i;
            } 
        }
 
        for(i=1;i<=len;++i)if(i&1)f[(i>>1)+1]=i-left[i]+1;
 
        Seg.Init(len/=2);
         
        for(i=1;i<=len;++i){
            if(i==f[i])g[i]=1;
            else g[i]=Seg.Query(i-f[i],i-1)+1;
            Seg.Modify(i,g[i]);
        }
 
        printf("%d\n",g[len]-1);
    }
 
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter