zoukankan      html  css  js  c++  java
  • zju3545

    AC自动机+状态压缩DP

    注意:相同的串可能出现多次,如果匹配成功则将各次权值加和。

    #include <cstdio>
    #include <queue>
    #include <cstring>
    using namespace std;
    
    #define D(x) 
    
    const int MAX_N = 15;
    const int MAX_LEN = 105;
    const int MAX_CHILD_NUM = 4;
    const int MAX_NODE_NUM = MAX_LEN * MAX_N;
    
    //1.init() 2.insert() 3.build() 4.query()
    struct Trie
    {
        int next[MAX_NODE_NUM][MAX_CHILD_NUM];
        int fail[MAX_NODE_NUM];
        int count[MAX_NODE_NUM];
        int node_cnt;
        bool vis[MAX_NODE_NUM]; //set it to false
        int root;
    
        void init()
        {
            node_cnt = 0;
            root = newnode();
            memset(vis, 0, sizeof(vis));
        }
    
        int newnode()
        {
            for (int i = 0; i < MAX_CHILD_NUM; i++)
                next[node_cnt][i] = -1;
            count[node_cnt++] = 0;
            return node_cnt - 1;
        }
    
        int get_id(char a)
        {
            if (a == 'A')
                return 0;
            if (a == 'T')
                return 1;
            if (a == 'C')
                return 2;
            return 3;
        }
    
        void insert(char buf[], int id)
        {
            int now = root;
            for (int i = 0; buf[i]; i++)
            {
                int id = get_id(buf[i]);
                if (next[now][id] == -1)
                    next[now][id] = newnode();
                now = next[now][id];
            }
            count[now] |= (1 << id);
        }
    
        void build()
        {
            queue<int>Q;
            fail[root] = root;
            for (int i = 0; i < MAX_CHILD_NUM; 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();
                for (int i = 0; i < MAX_CHILD_NUM; i++)
                    if (next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else
                    {
                        fail[next[now][i]]=next[fail[now]][i];
                        count[next[now][i]] |= count[fail[next[now][i]]];
                        Q.push(next[now][i]);
                    }
            }
        }
    
        int query(char buf[])
        {
            int now = root;
            int res = 0;
    
            memset(vis, 0, sizeof(vis));
            for (int i = 0; buf[i]; i++)
            {
                now = next[now][get_id(buf[i])];
                int temp = now;
                while (temp != root && !vis[temp])
                {
                    res += count[temp];
                     // optimization: prevent from searching this fail chain again.
                    //also prevent matching again.
                    vis[temp] = true;
                    temp = fail[temp];
                }
            }
            return res;
        }
    
        void debug()
        {
            for(int i = 0;i < node_cnt;i++)
            {
                printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],count[i]);
                for(int j = 0;j < MAX_CHILD_NUM;j++)
                    printf("%2d",next[i][j]);
                printf("]
    ");
            }
        }
    }ac;
    
    const int MAX_STATUS = (1 << 10) + 20;
    
    int n, len;
    char st[MAX_LEN];
    int w[MAX_N];
    bool dp[2][MAX_NODE_NUM][MAX_STATUS];
    
    int cal(int status)
    {
        int ret = 0;
        for (int i = 0; i < n; i++)
        {
            if (status & (1 << i))
                ret += w[i];
        }
        return ret;
    }
    
    int work()
    {
        int ret = -1;
        memset(dp, 0, sizeof(dp));
        dp[0][ac.root][0] = true;
        for (int i = 0; i < len; i++)
        {
            for (int j = 0; j < ac.node_cnt; j++)
                for (int status = 0; status < (1 << n); status++)
                    dp[(i + 1) & 1][j][status] = false;
            D(printf("%d
    ", dp[(i + 1) & 1][2][0]));
            for (int j = 0; j < ac.node_cnt; j++)
            {
                for (int status = 0; status < (1 << n); status++)
                {
                    if (!dp[i & 1][j][status])
                        continue;
                    for (int k = 0; k < 4; k++)
                    {
                        int v = ac.next[j][k];
                        dp[(i + 1) & 1][v][status | ac.count[v]] = true;
                        D(printf("%d %d
    ", j, status));
                        D(printf("%d %d %d %d
    ", (i + 1) & 1, v, status | ac.count[v], dp[(i + 1) & 1][0][1044]));
                    }
                }
            }
        }
        for (int i = 0; i < ac.node_cnt; i++)
            for (int status = 0; status < (1 << n); status++)
            {
                if (dp[len & 1][i][status])
                {
                    if (dp[len & 1][i][0] && status == 0)
                    {
                        D(printf("*%d %d
    ", i, ac.count[i]));
                    }
                    ret = max(ret, cal(status));
                }
            }
        return ret;
    }
    
    int main()
    {
        while (scanf("%d%d", &n, &len) != EOF)
        {
            ac.init();
            for (int i = 0; i < n; i++)
            {
                scanf("%s%d", st, &w[i]);
                ac.insert(st, i);
            }
            ac.build();
            int ans = work();
            if (ans < 0)
                puts("No Rabbit after 2012!");
            else
                printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ubuntu16.04上安装深度学习环境
    QQ音乐付费音乐下载的demo
    python列表按比例或长度拆分
    docker 使用gpu启动及tf限额
    python apscheduler was missed by
    k8s中使用gpu的部署方案
    从字符串中找出最大的数字串,字符串中可以带小数点。--python实现
    linux中批量删除带空格的文件
    tornado中使用python3原生事件循环asyncio
    mysql DATE_FORMAT FROM_UNIXTIME 的区别
  • 原文地址:https://www.cnblogs.com/rainydays/p/4372886.html
Copyright © 2011-2022 走看看