您的位置:首页 > 其它

hdu 4899 Hero meet devil

2016-07-10 22:48 393 查看
首先,LCS是可以在O(nlogn)下求出来的,只要将A串的元素x替换成x在B串中出现的所有位置的降序,最后求修改后的A串的LIS就可以了。

因为n很小,就可以直接状压维护在O(nlogn)求LIS时记录某个长度的子序列的最小结尾的数组了(如果该数出现,则置1)。预处理一下每个状态遇到A,T,C,G四个字母时会转变的状态,之后递推即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
const ll md=1000000007;ll dp[2][70000],rs[1001];
char cz[20],tz[4]={'A','T','C','G'};int n,m,ts[70000][4];
int _le(int x){int r=0;for(;x;x>>=1)r+=(x&1);return r;};
int _cl(int x,int a){
if(x&(1<<a))return x;
for(a=1<<a,x^=a,a<<=1;x>=a&&!(x&a);a<<=1);
return x&a?x^a:x;
};
void cl(){
int i,j,a,b,d,c,q,t;scanf("%s %d",cz,&m);n=strlen(cz);
clr(dp),c=0,q=1,dp[0][0]=1;
for(d=1<<n,i=0;i<d;++i)for(j=0;j<4;++j){
for(t=i,b=n-1;b>=0;--b)if(cz[b]==tz[j])t=_cl(t,b);
ts[i][j]=t;
}
for(i=0;i<m;++i,swap(c,q))for(clr(dp[q]),a=0;a<d;++a)
for(j=0;j<4;++j){
dp[q][t=ts[a][j]]+=dp[c][a];if(dp[q][t]>=md)dp[q][t]-=md;
}
for(clr(rs),i=0;i<d;++i){rs[a=_le(i)]+=dp[c][i];if(rs[a]>=md)rs[a]-=md;}
for(i=0;i<=n;printf("%I64d\n",rs[i++]));
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;scanf("%d",&t);
while(t--)cl();
return 0;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: