HDU2825

来源:互联网 发布:把字符串放到数组中 编辑:程序博客网 时间:2024/05/02 04:29

解题思路:

首先按照正常的思路将自动机模型建立起来。

然后就在上面进行DP其中DP[i][j][k].i表示字符串的字符的个数j表示的是最后一位是什么状态.k表示magic string的状态这是用状态压缩记录的也就是2^10。通过每一位01表示该个magic string是否被表示。


这道题开始的时候是TLE,是memset的问题。改了之后就狂WA。后来找到了WA的原因,但是没有办法改。因为对于3 2 2 she he这样的数据没有办法过。最开始的想法是将状态之间的关系记录在g[maxn][maxn] 。然后每次加入一个状态就判断这个状态表示的字符串是否为magic string 如果是 则记录。但是后来发现这样写会有一个很严峻的问题。比如she he 那样的例子就不能得到解。后来看了其他人的代码。发现他们对于每一个状态就加入了tag数组,记录该状态下的字符串包含多少的magic string。

上代码:



#include<cstdio>
#include<cstring>
using namespace std;
struct node{
    node *fail;
    node *next[26];
    int count;
    int id;
    bool end;
    int tag;
    node(){
        id=0;
        end=false;
        fail=NULL;
        count=0;
        tag=0;
        for(int i=0;i<=25;i++){
            next[i]=NULL;
        }
    }
};
const int  MAXN=110;
node *T[110];
node *q[500010];
node *root=new node();
int num=1;
void insert(char word[],int pp){
    node *cur=root;
    int i=0,branch;
    while(word[i]){
        branch=word[i]-'a';
        if(cur->next[branch]==NULL){
            cur->next[branch]=new node();
            T[num]=cur->next[branch];
            cur->next[branch]->id=num++;
        }
        i++;
        cur=cur->next[branch];
    }
    cur->end=true;
    cur->count++;
    cur->tag=1<<pp;
}
void AC(){
    int rear=1,front=0,i;
    node *cur;
    q[0]=root;
    root->fail=root;
    while(front!=rear){
        node *p=q[front++];
        p->end=p->end||p->fail->end;
        for(int i=0;i<=25;i++){
            if(p->next[i]==NULL){
                if(p==root)
                    p->next[i]=root;
                else
                    p->next[i]=p->fail->next[i];
            }
            else{
                if(p==root)
                    p->next[i]->fail=root;
                else{
                    p->next[i]->fail=p->fail->next[i];
                    p->next[i]->tag=p->next[i]->tag|p->fail->next[i]->tag;
                }
                q[rear++]=p->next[i];
            }
        }
    }
}
int magic[110],g[MAXN][MAXN];
int nnum=0;
void get_matrix(){
    int i,j;
    memset(g,0,sizeof(g));
    memset(magic,0,sizeof(magic));
    for(int i=0;i<num;i++){
        for(int j=0;j<=25;j++){
            if(T[i]->next[j]!=NULL)
                g[i][T[i]->next[j]->id]++;


        }
        if(T[i]->end==true){
            magic[i]=++nnum;
        }
    }
}
int dp[30][110][1300];
int f[20];
void ini(){
    f[0]=1;
    for(int i=1;i<=10;i++){
        f[i]=2*f[i-1];
    }
}
int mod=20090717;
int gg[MAXN][MAXN];
main(){
    int n,m,kk;
    char s[20];
    while(scanf("%d%d%d",&n,&m,&kk)!=-1 && !(n==0 && m==0 && kk==0)){
        num=1;nnum=0;root=new node();
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        insert(s,i-1);
    }
    AC();
    T[0]=root;
    root->id=0;
    get_matrix();
    for(int i=0;i<=n;i++)
        for(int j=0;j<=num;j++)
            for(int k=0;k<=1024;k++)
                dp[i][j][k]=0;
    ini();
   dp[0][0][0]=1;
    for(int i=0;i<num;i++){
        gg[i][0]=0;
        for(int j=0;j<num;j++){
            if(g[i][j]!=0){
                gg[i][++gg[i][0]]=j;
            }
        }
    }
    for(int i=0;i<=n-1;i++){
        for(int j=0;j<num;j++){
                for(int k=0;k<=1023;k++){
                    if(dp[i][j][k]!=0){
                        for(int x=1;x<=gg[j][0];x++){
                            int cnt=T[gg[j][x]]->tag;
                            dp[i+1][gg[j][x]][k|cnt]+=(dp[i][j][k]*g[j][gg[j][x]])%mod;
                            dp[i+1][gg[j][x]][k|cnt]=dp[i+1][gg[j][x]][k|cnt]%mod;
                        }
                    }
                }
        }
    }
    int ans=0;
    for(int i=0;i<num;i++){
        for(int j=0;j<=1023;j++){
            int flag=0;
            for(int k=0;k<=9;k++){
                int tmp=f[k]|j;
                if(tmp==j)
                    flag++;
            }
            if(flag>=kk && dp[n][i][j]!=0){
                ans+=dp[n][i][j];
                ans=ans%mod;
            }
        }
    }
    printf("%d\n",ans%mod);
    }
}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 太原回迁房多余的房子怎么办 回迁房被开发商抵押怎么办 回迁房源多开发商扣房怎么办 蝈蝈叫晚上怕吵怎么办 蝈蝈总不停的叫怎么办 按揭房没拿房产证夫妻离婚怎么办 按揭房子房产证还没有到离婚怎么办 结婚7年离婚孩子怎么办 合伙经营KTV股东意见不合怎么办 合伙生意转让意见不合怎么办 租完房子后悔了怎么办 通过中介买房产生纠纷怎么办 天津公租房资格证到期怎么办 买大房子后悔了怎么办 公款私存了该怎么办 外地人怎么办身份证在北京东城区 申请公租房有车怎么办 租了公租房辞职怎么办 申请公租房收入明细没有怎么办 杭州公租房满3年怎么办 小学寄读不转学籍手续怎么办 炸东西的油糊了怎么办 赠送面积为违建怎么办 执法不管违建我怎么办 司法考试毕业院校写错了怎么办 家具店西安一直拖着不交货怎么办 派出所私自迁移了我家户口怎么办? 退房子不退押金怎么办 租房子中介不退押金怎么办 租房子押金不退怎么办 外地人签户口到武汉怎么办 开发商不给办土地证怎么办 房间里的油烟味怎么办 现金借款app还不了款怎么办 学校不允许实习生自己租房怎么办 盯盯拍开不了机怎么办 向私人借钱不还怎么办 微信好友借钱不还怎么办 支付宝借不了钱怎么办 支付宝借条关了怎么办 qq群不小心解散了怎么办