题意:
给定最多十个最长不超过10的病毒dna串,求长度为m(m < 2e9)的串中不含病毒的有多少。
分析:
用自动机建立状态转移图,然后建立转移矩阵
定义初始状态为[1 , 0 , 0 , 0 ....]代表当前长度为0可转移到各个状态的方案数目,然后乘上m次转移矩阵即答案。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define rep(i,n) for(int i = 0; i<(int)n;i++) #define rep1(i,x,y) for(int i = x;i<(int)y;i++) const int N = 115; const int sigma_size = 4; char str[N]; const char* sss ="ATCG"; struct Trie { int ch[N][sigma_size]; int val[N]; int sz; void init() { sz = 1; memset(val , 0, sizeof(val)); memset(ch[0] , 0,sizeof(ch[0])); } int idx(char x) { rep(i ,4) if(sss[i] == x) return i; } void insert(char* s, int v) { int n = strlen(s) , u = 0; rep(i , n) { int c = idx(str[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = 1; } int f[N]; int last[N]; void getfail() { f[0] = 0; queue<int> q; rep(i , sigma_size) { if(ch[0][i]) { q.push(ch[0][i]); f[ch[0][i]] = last[ch[0][i]] = 0; } } while(!q.empty()) { int r = q.front(); q.pop(); if (val[f[r]]) val[r] = 1; /* 特别注意这个细节,当在自动机中转移到的下一个状态不仅要求该点不是结尾,也要求 该节点失配链中没有结尾*/ for(int c = 0; c < sigma_size ; c++) { int u = ch[r][c]; if(!u) { ch[r][c] = ch[f[r]][c]; continue; } q.push(u); f[u] = ch[f[r]][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } } } } trie; const int mod = 100000; int n , m; struct Matrix { int m[N][N]; Matrix() { memset(m , -1, sizeof(m)); } }; Matrix mul(Matrix A , Matrix B) { Matrix C; rep(i , n) rep(j , n) { C.m[i][j] = 0; rep(k , n) C.m[i][j] = ((ll)C.m[i][j] + (ll)A.m[i][k] * B.m[k][j] % mod ) % mod; } return C; } Matrix pow_mul(Matrix A , int b) { Matrix ans ; rep(i , n) rep(j ,n) ans.m[i][j] = (i == j); while(b > 0) { if(b & 1) ans = mul(ans , A); b>>=1; A = mul(A,A); } return ans; } Matrix A; void init() { rep(i , n) rep(j , n) A.m[i][j] = 0; rep(i , n) { rep(j , sigma_size) { if(!trie.val[i] && !trie.val[trie.ch[i][j]]) { A.m[i][trie.ch[i][j]]++; } } } } int main() { scanf("%d %d",&n,&m); trie.init(); rep(i , n) { scanf("%s",str); trie.insert(str , i +1); } trie.getfail(); n = trie.sz; init(); Matrix B = pow_mul(A , m); ll ans = 0; rep(i , n) ans = (ans + B.m[0][i]) % mod; printf("%d\n",(int)ans); return 0; }