求长度为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 ;
}