zoukankan      html  css  js  c++  java
  • poj3341

    AC自动机,用40^4 * 50 * 10的空间进行dp。

    最大的难点在于hash。

    hash一个数列f,数列中的每一位都有一个上限g,即f[i]<=g[i]。

    那么可以将该数列hash为这样一个整数,这个整数的每一个位的进制都不同,第i位的进制是g[i] + 1,即第i位满g[i]+1则可进位。(当然由于g[i]是该位的上限,所以永远不可能进位)

    用p[i]表示(g[0]+1)*(g[1]+1)*...*(g[i - 1]+1)。那么最终f被hash的结果是p[0]*f[0]+p[1]*f[1]+...。

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <cstring>
    using namespace std;
    
    #define D(x) 
    
    const int MAX_LEN = 50;
    const int MAX_N = 55;
    const int MAX_NODE_NUM = 12 * MAX_N;
    const int MAX_CHILD_NUM = 4;
    
    //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 == 'C')
                return 1;
            if (a == 'T')
                return 2;
            return 3;
        }
    
        void insert(char buf[])
        {
            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]++;
        }
    
        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;
    
    char st[MAX_LEN];
    int n;
    int num[4];
    int num2[4];
    int dp[15000][505];
    
    int myhash(int f[])
    {
        int ret = 0;
        for (int i = 0; i < 4; i++)
        {
            ret += f[i] * num[i];
        }
        return ret;
    }
    
    int work()
    {
        int temp[4] = {0};
        for (int i = 0; st[i]; i++)
        {
            temp[ac.get_id(st[i])]++;
        }
        num[3] = 1;
        for (int i = 2; i >= 0; i--)
        {
            num[i] = (temp[i + 1] + 1) * num[i + 1];
        }
        memset(dp, -1, sizeof(dp));
        int f[4];
        int g[4];
        int ret = 0;
        for (f[0] = 0; f[0] <= temp[0]; f[0]++)
            for (f[1] = 0; f[1] <= temp[1]; f[1]++)
                for (f[2] = 0; f[2] <= temp[2]; f[2]++)
                    for (f[3] = 0; f[3] <= temp[3]; f[3]++)
                    {
                        for (int u = 0; u < ac.node_cnt; u++)
                        {
                            int h = myhash(f);
                            for (int j = 0; j < 4; j++)
                            {
                                g[j] = f[j];
                            }
                            int temp2 = 0;
                            for (int j = 0; j < 4; j++)
                            {
                                g[j]--;
                                int h2 = myhash(g);
                                int v = ac.next[u][j];
                                if (g[j] >= 0)
                                {
                                    temp2 = max(temp2, dp[h2][v]);
                                    D(printf("			%d %d %d %d %d %d %d
    ", g[0], g[1], g[2], g[3], v, temp2, h2));
                                }
                                g[j]++;
                            }
                            dp[h][u] = temp2 + ac.count[u];
                            ret = max(ret, dp[h][u]);
                            D(printf("%d %d %d %d %d %d %d
    ", f[0], f[1], f[2], f[3], u, dp[h][u], h));
                        }
                    }
        return dp[myhash(temp)][ac.root];
    }
    
    int main()
    {
        int t = 0;
        while (scanf("%d", &n), n)
        {
            ac.init();
            for (int i = 0; i < n; i++)
            {
                scanf("%s", st);
                ac.insert(st);
            }
            ac.build();
            scanf("%s", st);
            printf("Case %d: %d
    ", ++t, work());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Masterha-manager避免自动关闭的方法
    MHA自动切换流程
    vue 使用keep-alive缓存tab切换组件,保持每个组件滚动条位置
    el-select 输入下拉搜索,匹配不到数据时也保留输入值,同时input获取焦点时保留其value值
    尝试 React16、React-router4 实现根据动态菜单生成按需加载的路由
    vue iscroll5滚动条组件
    vue项目中 axios请求拦截器与取消pending请求功能
    jquery编写的简单日历
    手机访问电脑wampServer本地环境页面
    ajax在ie下返回未定义解决方案
  • 原文地址:https://www.cnblogs.com/rainydays/p/4379205.html
Copyright © 2011-2022 走看看