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;
        
    }
  • 相关阅读:
    我认知的javascript之函数调用
    table 的宽度设置无效
    【转】微信读书排版引擎自动化测试方案
    RocksDB原理及应用
    ElasticSearch 架构及应用简介
    芝加哥大学论文写作指南 简述
    python 常用模块
    Flask-SQLAlchemy安装及设置
    selenium设置程序失败后重启
    获取临时IP加入临时列表使用
  • 原文地址:https://www.cnblogs.com/evenbao/p/10659997.html
Copyright © 2011-2022 走看看