zoukankan      html  css  js  c++  java
  • POJ

    这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数。

    题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的。

    根据AC自动机的tire图,我们可以获得一个可达矩阵。

    关于这题的tire图详解可以点击这里,往下面翻,这个博主的图对于tire图讲的非常详细。

    知道了什么是tire图,理解了tire图后,后面的AC自动机的题目才能写。

    AC自动机的灵魂应该就是tire图

    然后问题就变成了,得到了一个可达矩阵后,如何求方案数呢?

    这个n = 2000000000 这咋办呢?

    给定一个有向图,问从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即可。

    是不是就是一个裸的矩阵快速幂了。

    通过AC自动机得到可达矩阵,然后通过矩阵快速幂求方案数。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <set>
      7 #include <iostream>
      8 #include <map>
      9 #include <stack>
     10 #include <string>
     11 #include <ctime>
     12 #include <vector>
     13 
     14 #define  pi acos(-1.0)
     15 #define  eps 1e-9
     16 #define  fi first
     17 #define  se second
     18 #define  rtl   rt<<1
     19 #define  rtr   rt<<1|1
     20 #define  bug         printf("******
    ")
     21 #define  mem(a, b)    memset(a,b,sizeof(a))
     22 #define  name2str(x) #x
     23 #define  fuck(x)     cout<<#x" = "<<x<<endl
     24 #define  sf(n)       scanf("%d", &n)
     25 #define  sff(a, b)    scanf("%d %d", &a, &b)
     26 #define  sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
     27 #define  sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
     28 #define  pf          printf
     29 #define  FIN               freopen("../date.txt","r",stdin)
     30 #define  gcd(a, b)    __gcd(a,b)
     31 #define  lowbit(x)   x&-x
     32 
     33 using namespace std;
     34 typedef long long LL;
     35 typedef unsigned long long ULL;
     36 const int maxn = 3e3 + 7;
     37 const int maxm = 8e6 + 10;
     38 const int INF = 0x3f3f3f3f;
     39 const int mod = 100000;
     40 
     41 struct Matrix {
     42     int mat[110][110], n;
     43 
     44     Matrix() {}
     45 
     46     Matrix(int _n) {
     47         n = _n;
     48         for (int i = 0; i < n; i++)
     49             for (int j = 0; j < n; j++)
     50                 mat[i][j] = 0;
     51     }
     52 
     53     Matrix operator*(const Matrix &b) const {
     54         Matrix ret = Matrix(n);
     55         for (int i = 0; i < n; i++)
     56             for (int j = 0; j < n; j++)
     57                 for (int k = 0; k < n; k++) {
     58                     int tmp = (long long) mat[i][k] * b.mat[k][j] % mod;
     59                     ret.mat[i][j] = (ret.mat[i][j] + tmp) % mod;
     60                 }
     61         return ret;
     62     }
     63 };
     64 
     65 Matrix pow_M(Matrix a, int b) {
     66     Matrix ret = Matrix(a.n);
     67     for (int i = 0; i < ret.n; i++)
     68         ret.mat[i][i] = 1;
     69     Matrix tmp = a;
     70     while (b) {
     71         if (b & 1)ret = ret * tmp;
     72         tmp = tmp * tmp;
     73         b >>= 1;
     74     }
     75     return ret;
     76 }
     77 
     78 struct Aho_Corasick {
     79     int next[50010][4], fail[50010], End[50010];
     80     int root, cnt;
     81 
     82     int newnode() {
     83         for (int i = 0; i < 4; i++) next[cnt][i] = -1;
     84         End[cnt++] = 0;
     85         return cnt - 1;
     86     }
     87 
     88     void init() {
     89         cnt = 0;
     90         root = newnode();
     91     }
     92 
     93     int get_num(char ch) {
     94         if (ch == 'A') return 0;
     95         if (ch == 'T') return 1;
     96         if (ch == 'C') return 2;
     97         if (ch == 'G') return 3;
     98     }
     99 
    100     void insert(char buf[]) {
    101         int len = strlen(buf);
    102         int now = root;
    103         for (int i = 0; i < len; i++) {
    104             if (next[now][get_num(buf[i])] == -1) next[now][get_num(buf[i])] = newnode();
    105             now = next[now][get_num(buf[i])];
    106         }
    107         End[now]++;
    108     }
    109 
    110     void build() {
    111         queue<int> Q;
    112         fail[root] = root;
    113         for (int i = 0; i < 4; i++)
    114             if (next[root][i] == -1) next[root][i] = root;
    115             else {
    116                 fail[next[root][i]] = root;
    117                 Q.push(next[root][i]);
    118             }
    119         while (!Q.empty()) {
    120             int now = Q.front();
    121             Q.pop();
    122             if (End[fail[now]]) End[now] = 1;
    123             for (int i = 0; i < 4; i++)
    124                 if (next[now][i] == -1) next[now][i] = next[fail[now]][i];
    125                 else {
    126                     fail[next[now][i]] = next[fail[now]][i];
    127                     Q.push(next[now][i]);
    128                 }
    129         }
    130     }
    131 
    132     Matrix get_Matrix() {
    133         Matrix ret = Matrix(cnt);
    134         for (int i = 0; i < cnt; ++i) {
    135             for (int j = 0; j < 4; ++j) {
    136                 if (End[next[i][j]]) continue;
    137                 ret.mat[i][next[i][j]]++;
    138             }
    139         }
    140         return ret;
    141     }
    142 
    143     int query(char buf[]) {
    144         int len = strlen(buf);
    145         int now = root;
    146         int res = 0;
    147         for (int i = 0; i < len; i++) {
    148             now = next[now][buf[i] - 'a'];
    149             int temp = now;
    150             while (temp != root) {
    151                 res += End[temp];
    152                 End[temp] = 0;
    153                 temp = fail[temp];
    154             }
    155         }
    156         return res;
    157     }
    158 
    159     void debug() {
    160         for (int i = 0; i < cnt; i++) {
    161             printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
    162             for (int j = 0; j < 26; j++) printf("%2d", next[i][j]);
    163             printf("]
    ");
    164         }
    165     }
    166 } ac;
    167 
    168 int n, m;
    169 char str[maxn];
    170 
    171 int main() {
    172   //  FIN;
    173     sff(m, n);
    174     ac.init();
    175     for (int i = 0; i < m; ++i) {
    176         scanf("%s", str);
    177         ac.insert(str);
    178     }
    179     ac.build();
    180     Matrix mat = ac.get_Matrix();
    181     mat = pow_M(mat, n);
    182     LL ans = 0;
    183     for (int i = 0; i < mat.n; ++i) {
    184         ans = (ans + mat.mat[0][i]) % mod;
    185     }
    186     printf("%lld
    ", ans);
    187     return 0;
    188 }
    View Code

    考研路茫茫――单词情结 HDU - 2243

    这题和上题题意类似,做法一样。

    上题是说长度为n的不包含m个模式串的方案数,这题求的是长度为1~n不包括m个模式串的方案数。

    这题就在矩阵上面加上一列全为1的列,这个可以1保存了前面的方案书之和。

    如果不理解的话,建议通过手算一下矩阵,去看看这个新加的一列有什么用。

    这题是对2^64取模,所以直接用unsigned long long 自动溢出取模即可。

      1 #include <set>
      2 #include <map>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <cstdio>
      7 #include <string>
      8 #include <vector>
      9 #include <time.h>
     10 #include <cstring>
     11 #include <iostream>
     12 #include <algorithm>
     13 #include <unordered_map>
     14 
     15 #define  pi acos(-1.0)
     16 #define  eps 1e-9
     17 #define  fi first
     18 #define  se second
     19 #define  rtl   rt<<1
     20 #define  rtr   rt<<1|1
     21 #define  bug               printf("******
    ")
     22 #define  mem(a, b)         memset(a,b,sizeof(a))
     23 #define  name2str(x)       #x
     24 #define  fuck(x)           cout<<#x" = "<<x<<endl
     25 #define  sf(n)             scanf("%d", &n)
     26 #define  sff(a, b)         scanf("%d %d", &a, &b)
     27 #define  sfff(a, b, c)     scanf("%d %d %d", &a, &b, &c)
     28 #define  sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
     29 #define  pf                printf
     30 #define  FIN               freopen("../date.txt","r",stdin)
     31 #define  gcd(a, b)         __gcd(a,b)
     32 #define  lowbit(x)         x&-x
     33 #define  IO                iOS::sync_with_stdio(false)
     34 
     35 
     36 using namespace std;
     37 typedef long long LL;
     38 typedef unsigned long long ULL;
     39 const int maxn = 1e6 + 7;
     40 const int maxm = 8e6 + 10;
     41 const int INF = 0x3f3f3f3f;
     42 const int mod = 1e9 + 7;
     43 
     44 struct Matrix {
     45     ULL mat[110][110], n;
     46 
     47     Matrix() {}
     48 
     49     Matrix(int _n) {
     50         n = _n;
     51         for (int i = 0; i < n; i++)
     52             for (int j = 0; j < n; j++)
     53                 mat[i][j] = 0;
     54     }
     55 
     56     Matrix operator*(const Matrix &b) const {
     57         Matrix ret = Matrix(n);
     58         for (int i = 0; i < n; i++)
     59             for (int j = 0; j < n; j++)
     60                 for (int k = 0; k < n; k++)
     61                     ret.mat[i][j] = ret.mat[i][j] + mat[i][k] * b.mat[k][j];
     62         return ret;
     63     }
     64 };
     65 
     66 Matrix pow_M(Matrix a, LL b) {
     67     Matrix ret = Matrix(a.n);
     68     for (int i = 0; i < ret.n; i++)
     69         ret.mat[i][i] = 1;
     70     Matrix tmp = a;
     71     while (b) {
     72         if (b & 1)ret = ret * tmp;
     73         tmp = tmp * tmp;
     74         b >>= 1;
     75     }
     76     return ret;
     77 }
     78 
     79 struct Aho_Corasick {
     80     int next[10010][26], fail[10010], End[10010];
     81     int root, cnt;
     82 
     83     int newnode() {
     84         for (int i = 0; i < 26; i++) next[cnt][i] = -1;
     85         End[cnt++] = 0;
     86         return cnt - 1;
     87     }
     88 
     89     void init() {
     90         cnt = 0;
     91         root = newnode();
     92     }
     93 
     94     void insert(char buf[]) {
     95         int len = strlen(buf);
     96         int now = root;
     97         for (int i = 0; i < len; i++) {
     98             if (next[now][buf[i] - 'a'] == -1) next[now][buf[i] - 'a'] = newnode();
     99             now = next[now][buf[i] - 'a'];
    100         }
    101         End[now]++;
    102     }
    103 
    104     void build() {
    105         queue<int> Q;
    106         fail[root] = root;
    107         for (int i = 0; i < 26; i++)
    108             if (next[root][i] == -1) next[root][i] = root;
    109             else {
    110                 fail[next[root][i]] = root;
    111                 Q.push(next[root][i]);
    112             }
    113         while (!Q.empty()) {
    114             int now = Q.front();
    115             Q.pop();
    116             if (End[fail[now]]) End[now] = 1;
    117             for (int i = 0; i < 26; i++)
    118                 if (next[now][i] == -1) next[now][i] = next[fail[now]][i];
    119                 else {
    120                     fail[next[now][i]] = next[fail[now]][i];
    121                     Q.push(next[now][i]);
    122                 }
    123         }
    124     }
    125 
    126     Matrix get_Matrix() {
    127         Matrix ret = Matrix(cnt+1);
    128         for (int i = 0; i < cnt; ++i) {
    129             for (int j = 0; j < 26; ++j) {
    130                 if (!End[next[i][j]]) ret.mat[i][next[i][j]]++;
    131             }
    132         }
    133         for (int i = 0; i <= cnt; ++i) ret.mat[i][cnt] = 1;
    134         return ret;
    135     }
    136 
    137     int query(char buf[]) {
    138         int len = strlen(buf);
    139         int now = root;
    140         int res = 0;
    141         for (int i = 0; i < len; i++) {
    142             now = next[now][buf[i]];
    143             int temp = now;
    144             while (temp != root) {
    145                 res += End[temp];
    146                 End[temp] = 0;
    147                 temp = fail[temp];
    148             }
    149         }
    150         return res;
    151     }
    152 
    153     void debug() {
    154         for (int i = 0; i < cnt; i++) {
    155             printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
    156             for (int j = 0; j < 26; j++) printf("%2d", next[i][j]);
    157             printf("]
    ");
    158         }
    159     }
    160 } ac;
    161 
    162 
    163 
    164 char buf[1000010];
    165 LL n, m;
    166 
    167 int main() {
    168    // FIN;
    169     while (~scanf("%lld%lld", &n, &m)) {
    170         ac.init();
    171         for (int i = 0; i < n; ++i) {
    172             scanf("%s", buf);
    173             ac.insert(buf);
    174         }
    175         ac.build();
    176         Matrix mat = ac.get_Matrix();
    177         mat = pow_M(mat, m);
    178         ULL res = 0, ans = 0;
    179         for (int i = 0; i < mat.n; ++i) res += mat.mat[0][i];
    180         Matrix a = Matrix(2);
    181         a.mat[0][0] = 26, a.mat[1][0] = a.mat[1][1] = 1;
    182         a = pow_M(a, m);
    183         ans = a.mat[0][0] + a.mat[1][0];
    184         ans -= res;
    185         printf("%llu
    ", ans);
    186     }
    187     return 0;
    188 }
    View Code
  • 相关阅读:
    Gibbs Sampling深入理解
    MCMC算法深入理解
    蒙特卡洛法
    马尔科夫链及其平稳状态
    Dirichlet分布深入理解
    xmldecoder漏洞
    基于BindingSource的WinForm开发
    .net WinForm 的数据绑定
    C#获取网页的HTML码、下载网站图片
    4步win7下简单FTP服务器搭建(试验成功)
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/11375935.html
Copyright © 2011-2022 走看看