求长度为M的DNA串不包含模式串的有多少个。
step1::先考虑另外一个问题,给你一个有向图,从某个点出发走n步到其他任意点,问不同的走法。
对这个问题构造一个矩阵,matrix[i][j]表示从i到j有几条边,然后这个矩阵自乘n次就是答案。
step2 : 点击打开链接点击打开链接
2张图片均转自上述衔接博客,感谢。
typedef long long LL ; const LL mod = 100000 ; int matn ; struct Mat{ LL x[108][108] ; Mat(){ memset(x , 0 , sizeof(x)) ; } Mat(int){ memset(x , 0 , sizeof(x)) ; for(int i = 0 ; i < matn ; i++) x[i][i] = 1 ; } }; Mat operator * (Mat a , Mat b){ Mat s ; int n = matn , i , j , k ; for(i = 0 ; i < n ; i++){ for(j = 0 ; j < n ; j++){ if(a.x[i][j] == 0) continue ; for(k = 0 ; k < n ; k++){ s.x[i][k] += a.x[i][j] * b.x[j][k] ; s.x[i][k] %= mod ; } } } return s ; } Mat Pow(Mat x , int y){ Mat s(1) ; for(; y ; y >>= 1){ if(y & 1) s = s * x ; x = x * x ; } return s ; } /*AC-------------*/ const int maxn = 108*4 ; const int kind = 4 ; int next[maxn][kind] ; int fail[maxn] ; int id[maxn] ; struct AC{ int root , n ; int newnode(){ id[n] = 0 ; for(int i = 0 ; i < kind ; i++) next[n][i] = -1 ; return n++ ; } void Init(){ n = 0 ; root = newnode() ; } int to(char c){ if(c == 'A') return 0 ; else if(c == 'C') return 1 ; else if(c == 'T') return 2 ; else return 3 ; } void Insert(char *s){ int now = root , k ; while(*s){ k = to(*s) ; if(next[now][k] == -1) next[now][k] = newnode() ; now = next[now][k] ; s++ ; } id[now] = 1 ; } void makeAc(){ queue<int> q ; fail[root] = root ; int now , i ; for(i = 0 ; i < kind ; i++){ if(next[root][i] == -1) next[root][i] = root ; else{ fail[next[root][i]] = root ; q.push(next[root][i]) ; } } while(! q.empty()){ now = q.front() ; q.pop() ; if(id[fail[now]] == 1) id[now] = 1 ; for(i = 0 ; i < kind ; i++){ if(next[now][i] == -1) next[now][i] = next[fail[now]][i] ; else{ fail[next[now][i]] = next[fail[now]][i] ; q.push(next[now][i]) ; } } } } Mat getMat(){ matn = n ; Mat s ; for(int i = 0 ; i < n ; i++){ if(id[i]) continue ; for(int j = 0 ; j < kind ; j++){ if(id[next[i][j]] == 0){ s.x[i][next[i][j]]++ ; } } } return s ; } }ac ; /*EndAc---------------*/ char word[18] ; int main(){ int t , n , i , m ,j ; while(cin>>n>>m){ ac.Init() ; for(i = 1 ; i <= n ; i++){ scanf("%s" , word) ; ac.Insert(word) ; } ac.makeAc() ; Mat a = ac.getMat() ; a = Pow(a , m) ; LL sum = 0 ; for(i = 0 ; i < matn ; i++){ sum += a.x[0][i] ; sum %= mod ; } cout<<sum<<endl ; } return 0 ; }