• poj2778DNA Sequence(AC自动机+矩阵乘法)


    链接

    看此题前先看一下matrix67大神写的关于十个矩阵的题目中的一个,如下:

    经典题目8 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
        把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

    再来看此题,与1627是如此的相似,又如此的不同,怒把长度涨到20Y,普通的dp转移无法奏效。

    既然已经贴上了大神的讲解,肯定与之有关系,姑且直接拉近距离,我们建立的trie树是有路径可寻的,从root往下走,显然,它是一个有向图,root->a可达 说明他俩之间右边,

    抛开病毒不病毒的不讲,长度为n的字符串数不就是从root走n步到达某个j结点的方案数?,那么此题就基本解决了,最后一点是构造A这个矩阵,需要当前结点不为病毒结点。

      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stdlib.h>
      6 #include<vector>
      7 #include<cmath>
      8 #include<queue>
      9 #include<set>
     10 using namespace std;
     11 #define N 101
     12 #define LL long long
     13 #define INF 0xfffffff
     14 #define mod 100000
     15 const double eps = 1e-8;
     16 const double pi = acos(-1.0);
     17 const double inf = ~0u>>2;
     18 const int child_num = 4;
     19 const int _n = 101;
     20 char vir[11];
     21 struct Mat
     22 {
     23     LL mat[N][N];
     24 };
     25 Mat operator * (Mat a,Mat b)
     26 {
     27     Mat c;
     28     memset(c.mat,0,sizeof(c.mat));
     29     int i,j,k;
     30     for(k =0 ; k < _n ; k++)
     31     {
     32         for(i = 0 ; i < _n ;i++)
     33         {
     34             if(a.mat[i][k]==0) continue;//优化
     35             for(j = 0 ;j < _n;j++)
     36             {
     37                 if(b.mat[k][j]==0) continue;//优化
     38                 c.mat[i][j] = (c.mat[i][j]+(a.mat[i][k]*b.mat[k][j])%mod)%mod;
     39             }
     40         }
     41     }
     42     return c;
     43 }
     44 Mat operator ^(Mat a,int k)
     45 {
     46     Mat c;
     47     int i,j;
     48     for(i =0 ; i < _n ;i++)
     49         for(j = 0; j < _n ;j++)
     50         c.mat[i][j] = (i==j);
     51     for(; k ;k >>= 1)
     52     {
     53         if(k&1) c = c*a;
     54         a = a*a;
     55     }
     56     return c;
     57 }
     58 class AC
     59 {
     60     private:
     61     int ch[N][child_num];
     62     int Q[N];
     63     int fail[N];
     64     int val[N];
     65     int id[128];
     66     int sz;
     67     public:
     68     void init()
     69     {
     70         fail[0] = 0;
     71         id['A'] = 0; id['G'] = 1;
     72         id['T'] = 2; id['C'] = 3;
     73     }
     74     void reset()
     75     {
     76         memset(val,0,sizeof(val));
     77         memset(fail,0,sizeof(fail));
     78         memset(ch[0],0,sizeof(ch[0]));
     79         sz = 1;
     80     }
     81     void insert(char *s,int key)
     82     {
     83         int i,k = strlen(s);
     84         int p = 0;
     85         for(i = 0 ;i < k ;i++)
     86         {
     87             int d = id[s[i]];
     88             if(ch[p][d]==0)
     89             {
     90                 memset(ch[sz],0,sizeof(ch[sz]));
     91                 ch[p][d] = sz++;
     92             }
     93             p = ch[p][d];
     94         }
     95         val[p] = key;
     96     }
     97     void construct()
     98     {
     99         int i,head=0,tail = 0;
    100         for(i = 0 ; i < child_num ; i++)
    101         {
    102             if(ch[0][i])
    103             {
    104                 Q[tail++] = ch[0][i];
    105                 fail[ch[0][i]] = 0;
    106             }
    107         }
    108         while(head!=tail)
    109         {
    110             int u = Q[head++];
    111             val[u]|=val[fail[u]];
    112             for(i = 0 ;i < child_num ; i++)
    113             {
    114                 if(ch[u][i])
    115                 {
    116                     Q[tail++] = ch[u][i];
    117                     fail[ch[u][i]] = ch[fail[u]][i];
    118                 }
    119                 else ch[u][i] = ch[fail[u]][i];
    120             }
    121         }
    122     }
    123     void work(int n)
    124     {
    125         Mat x;
    126         int i,j;
    127         memset(x.mat,0,sizeof(x.mat));
    128         for(i = 0 ; i < sz ; i++)
    129             for(j = 0; j < child_num ; j++)
    130             if(!val[ch[i][j]])
    131             x.mat[i][ch[i][j]]++;
    132         x = x^n;
    133         int ans = 0;
    134         for(i = 0 ;i < sz ; i++)
    135         ans = (ans+x.mat[0][i])%mod;
    136         printf("%d
    ",ans);
    137     }
    138 }ac;
    139 int main()
    140 {
    141     int m,n;
    142     ac.init();
    143     while(cin>>m>>n)
    144     {
    145         ac.reset();
    146         while(m--)
    147         {
    148             scanf("%s",vir);
    149             ac.insert(vir,1);
    150         }
    151         ac.construct();
    152         ac.work(n);
    153     }
    154     return 0;
    155 }
    View Code
  • 相关阅读:
    verilog学习(9)实战之存储器&奇偶校验
    求职经验之综合岗位三面
    求职经验之综合岗位二面
    求职经验之综合岗位
    verilog学习(8)实战之PPL与串行/解串器
    verilog学习(7)实战之扫描链
    verilog学习(6)实战4之触发器与锁存器
    verilog学习(5)实战3之计数器与bus
    verilog学习(4)实战1之基础练习
    求职经验之器件与芯片岗
  • 原文地址:https://www.cnblogs.com/shangyu/p/3731108.html
Copyright © 2020-2023  润新知