BZOJ5336 DP套DP

https://www.lydsy.com/JudgeOnline/problem.php?id=5336

萌新第一次写dp套dp.

先不考虑有NOI的限制.

考虑普通lcs是怎么做的.

f[i][j]=max(f[i-1][j],f[i][j-1],(f[i-1][j-1]+1)*[S[i]==T[j]]).

设f[i]表示对于原串,生出串做到第i的位置时,最长公共子序列长度.

发现相邻的i-1~i只会f值最多+1,于是可以对这个状态进行差分后,状压存储.

预处理出在状态S后添加字符w[i],所得到的新的f[].

设dp[i][S][len]表示dp到第i位,f的差分后状态位S,匹配NOI字符串的长度为len.

添加字符w有

dp[i][trans[S][w]][mp[len][w]]+=dp[i-1][S][len].

#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,s,t) for(register int i=s;i<=t;++i)
#define _rep(i,s,t) for(register int i=s;i>=t;--i)
#define Rep(i,s,t) for(register int i=s;i<t;++i)
#define go(x) for(register int e=las[x];e;e=nxt[e])
#define re register
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
#define pb push_back
#define pii pair<int,int>
#define gi(x) read(x)
#define gii(x,y) read(x),read(y)
#define giii(x,y,z) read(x),read(y),read(z)
#define ms(f,x) memset(f,x,sizeof f)
namespace IO{
    #define gc getchar()
    #define pc(x) putchar(x)
    template<typename T>inline void read(T &x){
        x=0;int f=1;char ch=gc;while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc;x*=f;return;
    }
    template<typename T>inline void write(T x=0){
        T wr[51];wr[0]=0;if(x<0)pc('-'),x=-x;if(!x)pc(48);
        while(x)wr[++wr[0]]=x%10,x/=10;while(wr[0])pc(48+wr[wr[0]--]);return;
    }
}
using IO::read;
using IO::write;
typedef long long ll;
typedef double db;
using namespace std;
const int mod=1e9+7;
char w[]={'N','O','I'};
char ch[20];
int n,m,S;
int f[2][1<<15][3],mp[3][3],ans[1011];
int g[20],h[20],trans[1<<15][3],sz[1<<15];
inline void inc(int &x,int y){
    x+=y;
    if(x>=mod)x-=mod;
}
inline int zip(int *h){
    re int s=0;
    rep(i,1,n)
        s|=((h[i]-h[i-1])<<(i-1));
    return s;
}
inline void unzip(int *h,int s){
    rep(i,1,n)
        h[i]=h[i-1]+(s&1),s>>=1;
}
inline void init(){
    rep(i,1,S)sz[i]=sz[i>>1]+(i&1);
    rep(k,0,2)rep(s,0,S){
        unzip(g,s),ms(h,0);
        rep(i,1,n){
            h[i]=max(h[i-1],g[i]);
            if(w[k]==ch[i])
                h[i]=max(h[i],g[i-1]+1);
        }
        trans[s][k]=zip(h);
    }
}
int main(){
    gii(m,n),scanf("%s",ch+1),S=(1<<n)-1,init();
    mp[0][0]=mp[1][0]=mp[2][0]=f[0][0][0]=1,mp[1][1]=2;
    rep(i,1,m){
        int p=i&1,q=p^1;
        ms(f[p],0);
        rep(s,0,S)rep(j,0,2)rep(k,0,2){
            if(k==2&&j==2)continue;
            re int y=trans[s][k];
            inc(f[p][y][mp[j][k]],f[q][s][j]);  
        }
    }
    rep(s,0,S)rep(j,0,2)
        inc(ans[sz[s]],f[m&1][s][j]);
    rep(i,0,n)
        printf("%d\n",ans[i]);
    return 0;
}
BZOJ5336

 

posted @ 2018-05-21 20:58  Stump  阅读(268)  评论(0编辑  收藏