• hdu_3341_Lost's revenge(AC自动机+状态hashDP)


    题目链接:hdu_3341_Lost's revenge

    题意:

    有n个模式串,一个标准串,现在让标准串重组,使得包含最多的模式串,可重叠,问重组后最多包含多少模式串

    题解:

    显然是AC自动机上的状态压缩DP,不过如果直接开404*500的数组显示开不下,所以这样要将状态hash一下,然后再DP,因为这个字母加起来为40,所以状态数不超过15000,所以可以接受。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int AC_N=100*11,tyn=4;//数量乘串长,类型数
     6 struct AC_automation{
     7     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
     8     inline int getid(char x){
     9         if(x=='A')return 0;
    10         if(x=='C')return 1;
    11         if(x=='G')return 2;
    12         return 3;
    13     }
    14     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
    15     void init(){tot=-1,fail[0]=-1,nw();}
    16     void insert(char *s,int x=0){
    17         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
    18             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
    19         cnt[x]++;//串尾标记
    20     }
    21     void build(int head=1,int tail=0){
    22         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
    23         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
    24             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i],cnt[tr[x][i]]+=cnt[tr[fail[x]][i]];
    25             else tr[x][i]=tr[fail[x]][i];
    26     }
    27     
    28 }AC;
    29 
    30 inline void up(int &a,int b){if(a<b)a=b;}
    31 
    32 char s[100];
    33 int n,len,cnt,ic=0,na,nc,ng,nt;
    34 int hsh[41][41][41][41],dp[15000][501];
    35 
    36 void fuck()
    37 {
    38     int ed=0,ans=0;
    39     na=nc=ng=nt=0;
    40     for(int i=0;s[i]!='';i++)if(s[i]=='A')na++;
    41     else if(s[i]=='C')nc++;
    42     else if(s[i]=='G')ng++;
    43     else nt++;
    44     F(i,0,na)F(j,0,nc)F(k,0,ng)F(l,0,nt)hsh[i][j][k][l]=ed++;
    45     memset(dp,-1,sizeof(dp)),dp[0][0]=0;
    46     F(i,0,na)F(j,0,nc)F(k,0,ng)F(l,0,nt)if(i+j+k+l!=0)
    47     {
    48         int x1=hsh[i][j][k][l],x2;
    49         F(ii,0,AC.tot)F(jj,0,3)
    50         {
    51             if(jj==0&&i-1>=0)x2=hsh[i-1][j][k][l];
    52             else if(jj==1&&j-1>=0)x2=hsh[i][j-1][k][l];
    53             else if(jj==2&&k-1>=0)x2=hsh[i][j][k-1][l];
    54             else if(jj==3&&l-1>=0)x2=hsh[i][j][k][l-1];
    55             else continue;
    56             if(dp[x2][ii]==-1)continue;
    57             int now=AC.tr[ii][jj];
    58             up(dp[x1][now],dp[x2][ii]+AC.cnt[now]);
    59             up(ans,dp[x1][now]);
    60         }
    61     }
    62     printf("Case %d: %d
    ",++ic,ans);
    63 }
    64 
    65 int main()
    66 {
    67     while(scanf("%d",&n),n)
    68     {
    69         AC.init();
    70         F(i,1,n)scanf("%s",s),AC.insert(s);
    71         AC.build(),scanf("%s",s),fuck();
    72     }
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    查询是哪个进程占用了特定端口
    (面向c#开发人员) 编写javascript的好习惯一 false 值
    onerror 事件 如何使用 onerror 事件捕获网页中的错误。(chrome、opera、safari 浏览器不支持)
    查找url里面的flag元素判断操作
    jquery 弹出窗
    向上滚动
    kissy helpcenter
    kissyAPI
    IE6 动态创建 iframe 无法显示的 bug 芒果
    图片轮换动画仿GIF
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5826346.html
Copyright © 2020-2023  润新知