分析

未知定长串中不同已知模板串的出现次数问题,一般做法是AC自动机上dp。

考虑背包,\(dp(i,j,k)\)表示当前串长为\(i\),在AC自动机上对应节点\(j\),已匹配的模板串的状态为\(k\)的情况是否出现。用刷表法向后转移。先枚举不定串长度,再枚举AC自动机上节点,然后枚举已知状态,最后枚举字母边转移。

时间复杂度\(O(l \cdot MaxNode \cdot 2^n \cdot SigmaSize)\)。第一维可以滚动,空间复杂度\(O(MaxNode \cdot 2^n)\)

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1010;
const int SigmaSize=4;

bool dp[2][MAXN][1100];
int mp[15];

struct Trie
{
    int next[MAXN][SigmaSize];
    int fail[MAXN];
    int end[MAXN];
    int root,ncnt;
    int newnode()
    {
        for(int i=0;i<SigmaSize;++i)
            next[ncnt][i]=-1;
        end[ncnt++]=0;
        return ncnt-1;
    }
    void init()
    {
        ncnt=0;
        root=newnode();
    }
    int id(char c)
    {
        if(c=='A')
            return 0;
        else if(c=='G')
            return 1;
        else if(c=='T')
            return 2;
        else
            return 3;
    }
    void insert(char*str,int v)
    {
        int now=root;
        int len=strlen(str);
        for(int i=0;i<len;++i)
        {
            int c=id(str[i]);
            if(next[now][c]==-1)
                next[now][c]=newnode();
            now=next[now][c];
        }
        end[now]|=(1<<v);
    }
    void getfail()
    {
        queue<int>Q;
        fail[root]=root;
        for(int i=0;i<SigmaSize;++i)
        {
            if(next[root][i]==-1)
                next[root][i]=root;
            else
            {
                fail[next[root][i]]=root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            end[now]|=end[fail[now]];
            for(int i=0;i<SigmaSize;++i)
            {
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }
    void solve(int n,int l)
    {
        memset(dp,0,sizeof(dp));
        dp[0][0][0]=1; // dp[len][node][state]
        int cur=1;
        for(int i=1;i<=l;++i)
        {
            memset(dp[cur],0,sizeof(cur));
            for(int j=0;j<ncnt;++j)
            {
                for(int k=0;k<(1<<n);++k)
                {
                    for(int q=0;q<SigmaSize;++q)
                    {
                        int nxt=next[j][q];
                        dp[cur][nxt][k|end[nxt]]=(dp[cur][nxt][k|end[nxt]]||dp[cur^1][j][k]);
                    }
                }
            }
            cur^=1;
        }
        int ans=-INF;
        for(int i=0;i<ncnt;++i)
            for(int j=0;j<(1<<n);++j)
            {
                if(dp[cur^1][i][j])
                {
                    int sum=0;
                    for(int k=0;k<n;++k)
                        if(j&(1<<k))
                            sum+=mp[k];
                    ans=max(ans,sum);
                }
            }
        if(ans<0)
            printf("No Rabbit after 2012!\n");
        else
            printf("%d\n",ans);
    }
}AC;

char s[110];

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n,l,w;
    while(~scanf("%d %d",&n,&l))
    {
        AC.init();
        for(int i=0;i<n;++i)
        {
            scanf("%s %d",s,&w);
            AC.insert(s,i);
            mp[i]=w;
        }
        AC.getfail();
        AC.solve(n,l);
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

ZOJ3545 Rescue the Rabbit的更多相关文章

  1. JSOI2009 密码 和 JSOI2007 文本生成器 和 ZOJ3545 Rescue the Rabbit

    密码 众所周知,密码在信息领域起到了不可估量的作用.对于普通的登陆口令,唯一的破解 方法就是暴力破解一逐个尝试所有可能的字母组合,但这是一项很耗时又容易被发现的工 作.所以,为了获取对方的登陆口令,在 ...

  2. HDU-4057 Rescue the Rabbit(AC自动机+DP)

    Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hdu4057 Rescue the Rabbit

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=4057 题目: Rescue the Rabbit Time Limit: 20000/10000 MS ( ...

  4. hdu4057 Rescue the Rabbit(AC自己主动机+DP)

    Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  5. HDU4057 Rescue the Rabbit(AC自动机+状压DP)

    题目大概是给几个DNA片段以及它们各自的权值,如果一个DNA包含某个片段那么它的价值就加上这个片段的权值,同时包含多个相同DNA片段也只加一次,问长度l的DNA可能的最大价值. 与HDU2825大同小 ...

  6. HDU 4057 Rescue the Rabbit(AC自动机+DP)

    题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...

  7. ZOJ 3545 Rescue the Rabbit(AC自动机+状压DP)(The 2011 ACM-ICPC Asia Dalian Regional Contest)

    Dr. X is a biologist, who likes rabbits very much and can do everything for them. 2012 is coming, an ...

  8. 【HDOJ】4057 Rescue the Rabbit

    挺有意思的一道题目,解法是AC自动机+DP.AC自动机建立fail指针时,一定要注意结点的属性也需要传递.AC自动机结合了trie和kmp的优点.需要注意的是,每个模式串仅计算一次,否则这题很难解. ...

  9. Zoj 3545 Rescue the Rabbit(ac自己主动机+dp)

    标题效果: 鉴于DNA有一个正确的顺序值.请构造一个长度I的DNA在这个序列使DNA正确的顺序值极大.它被认为是负的输出噼啪. .. IDEAS: 施工顺序是,ac己主动机上走,求最大要用到dp dp ...

随机推荐

  1. java通过java.net.URL发送http请求调用接口

    一般在*.html,*.jsp页面中我们通过使用ajax调用接口,这个是我们通常用的.对于这些接口,大都是本公司写的接口供自己调用,所以直接用ajax就可以.但是,如果是多家公司共同开发一个东西,一个 ...

  2. CentOS7 Install Docker(转)

    https://linux.cn/article-4340-1.html CentOS 7 中 Docker 的安装 Docker 软件包已经包括在默认的 CentOS-Extras 软件源里.因此想 ...

  3. jquery自动填充输入框

    1,这是一个比较简单的页面,你可以复制下来就可以使用.<!doctype html><html lang="en"><head> <met ...

  4. linux单用户模式

    linux单用户模式 2014年11月11日 17:18 在grub上相应要启动的内核上按“e”. 进入下一界面,继续按“e”. 在进入文本界面后,输入“single”回车. 进入grub界面后,按“ ...

  5. 自定义DateTimeInput(时间)控件的显示格式

    DateTimeInput控件已有的几种格式可以在Format属性中选择: 但这几种格式仍无法满足我的要求怎么办? 例如想将显示格式定为类似这样的格式:2010-06-11 20:02:52,两步搞定 ...

  6. vue 表单校验(二)

    vue 表单校验(二) vue element-ui表单校验 由于现在使用element-ui进行form表单校验,因而使用其自带的校验规则进行校验,发现有些并不是那么好校验,或者说是校验起来很繁琐, ...

  7. Idea检入boss项目

    Idea检入boss项目  

  8. PHP:第三章——PHP中的回调函数

    <?php header("Content-Type:text/html;charset=utf-8"); //回调函数 //计算两个数只和 function Add($a, ...

  9. WEB-ERROR-PAGE

    首先需要在Web.xml文件中配置如下标签:     <error-page>        <error-code>404 </error-code>       ...

  10. String比较相等的问题探索

    String比较相等的问题探索 工作上,有个同事犯了个低级错误,把字符串的计较用了==.由于代码已经交付客户,上了生产环境,给公司带了了损失.于是看了他的代码,自己根据以前学的知识,写了几个小demo ...