zoukankan      html  css  js  c++  java
  • [TJOI2018] 碱基序列

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=5337

    [算法]

             考虑构建后缀自动机

             用fi , j表示前i个串 , 匹配到自动机上的j号节点方案数

             在自动机上dp即可 ,  详见代码 

             时间复杂度 : O(NK)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int N = 20010;
    const int ALPHA = 26;
    const int P = 1e9 + 7;
    
    #define rint register int
    
    int k;
    char s[N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    
    struct Suffix_Automaton
    {
            int sz , last;
            int father[N] , child[N][ALPHA] , depth[N] , dp[2][N] , size[N];
            vector< int > a[N];
            Suffix_Automaton()
            {
                    sz = 1;
                    last = 1;
            }
            inline int new_node(int dep)
            {
                    depth[++sz] = dep;
                    father[sz] = 0;
                    memset(child[sz] , 0 , sizeof(child[sz]));
                    return sz;
            }
            inline void extend(int ch)
            {
                    int np = new_node(depth[last] + 1);
                    int p = last;
                    for (; child[p][ch] == 0; p = father[p]) 
                            child[p][ch] = np;
                    if (child[p][ch] == np)
                            father[np] = 1;
                    else
                    {
                            int q = child[p][ch];
                            if (depth[q] == depth[p] + 1)
                                    father[np] = q;
                            else
                            {
                                    int nq = new_node(depth[last] + 1);
                                    father[nq] = father[q];
                                    father[np] = father[q] = nq;
                                    memcpy(child[nq] , child[q] , sizeof(child[nq]));
                                    for (; child[p][ch] == q; p = father[p])
                                            child[p][ch] = nq;
                            }
                    }
                    last = np;
                    size[np] = 1;
            }
            inline void insert(char *s)
            {
                    last = 1;
                    for (rint i = 1; i <= strlen(s + 1); ++i)
                            extend(s[i] - 'A');        
            }        
            inline void dfs(int u , int par)
            {
                    for (unsigned i = 0; i < a[u].size(); ++i)
                    {
                            if (a[u][i] != par)
                            {
                                    dfs(a[u][i] , u);
                                    size[u] += size[a[u][i]];
                            }
                    }
            }
            inline void update(int &x , int y)
            {
                    x += y;
                    while (x >= P) x -= P; 
            } 
            inline int find(int now , char *s)
            {
                    for (rint i = 1; i <= strlen(s + 1); ++i)
                            if (!child[now][s[i] - 'A']) return -1;
                            else now = child[now][s[i] - 'A'];
                    return now;
            }
            inline void calc()
            {
                    for (rint i = 2; i <= sz; ++i)
                            a[father[i]].push_back(i);
                    dfs(1 , 0);
                    dp[0][1] = 1;
                    for (rint i = 1; i <= k; ++i)
                    {
                            int cnt;
                            int now = i & 1 , pre = now ^ 1;
                            read(cnt);
                            for (rint j = 1; j <= sz; ++j) dp[now][j] = 0;
                            for (rint j = 1; j <= cnt; ++j)
                            {
                                    scanf("%s" , s + 1);
                                    for (rint frm = 1; frm <= sz; ++frm)
                                    {
                                            int to = find(frm , s);
                                            if (to != -1) 
                                                    update(dp[now][to] , dp[pre][frm]);
                                    }
                            }
                    }
                    int ans = 0;
                    for (rint i = 1; i <= sz; ++i) 
                            update(ans , 1LL * size[i] * dp[k & 1][i] % P);
                    printf("%d
    " , ans);
            }
    } SAM;
    
    int main()
    {
            
            read(k); 
            scanf("%s" , s + 1);
            SAM.insert(s);
            SAM.calc();
            
            return 0;
        
    }
  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/evenbao/p/10659997.html
Copyright © 2011-2022 走看看