题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种。
思路:用AC自动机,利用AC自动机上的节点做矩阵乘法。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #define MOD 100000 9 char s[2005]; 10 int ch(char x){ 11 if (x==‘A‘) return 0; 12 if (x==‘C‘) return 1; 13 if (x==‘G‘) return 2; 14 if (x==‘T‘) return 3; 15 return -1; 16 } 17 struct Trie{ 18 int fail[1005],next[1005][5],end[1005],L,root; 19 int newnode(){ 20 for (int i=0;i<4;i++) 21 next[L][i]=-1; 22 end[L++]=-1; 23 return L-1; 24 } 25 void clear(){ 26 L=0; 27 root=newnode(); 28 } 29 void insert(char s[]){ 30 int len=strlen(s),now=root; 31 for (int i=0;i<len;i++){ 32 if (next[now][ch(s[i])]==-1) next[now][ch(s[i])]=newnode(); 33 now=next[now][ch(s[i])]; 34 } 35 end[now]=1; 36 } 37 void build(){ 38 std::queue<int>Q; 39 int now; 40 for (int i=0;i<4;i++) 41 if (next[root][i]==-1) 42 next[root][i]=root; 43 else{ 44 fail[next[root][i]]=root; 45 Q.push(next[root][i]); 46 } 47 while (!Q.empty()){ 48 now=Q.front();Q.pop(); 49 if (end[fail[now]]==1) end[now]=1; 50 for (int i=0;i<4;i++){ 51 if (next[now][i]==-1) next[now][i]=next[fail[now]][i]; 52 else{ 53 fail[next[now][i]]=next[fail[now]][i]; 54 Q.push(next[now][i]); 55 } 56 } 57 } 58 } 59 }ac; 60 struct Matrix{ 61 int n,mx[105][105]; 62 Matrix(){} 63 Matrix(int x){ 64 n=x; 65 for (int i=0;i<n;i++) 66 for (int j=0;j<n;j++) 67 mx[i][j]=0; 68 } 69 }; 70 Matrix operator *(Matrix a,Matrix b){ 71 int n=a.n; 72 Matrix c=Matrix(n); 73 for (int i=0;i<n;i++) 74 for (int j=0;j<n;j++) 75 for (int k=0;k<n;k++){ 76 int tmp=(long long) a.mx[i][k]*b.mx[k][j]%MOD; 77 c.mx[i][j]=(c.mx[i][j]+tmp)%MOD; 78 } 79 return c; 80 } 81 Matrix powm(Matrix t,int m){ 82 Matrix r=Matrix(t.n); 83 for (int i=0;i<=t.n;i++) 84 r.mx[i][i]=1; 85 while (m){ 86 if (m%2) r=r*t; 87 t=t*t; 88 m/=2; 89 } 90 return r; 91 } 92 int main(){ 93 int m; 94 int n; 95 while (scanf("%d%d",&n,&m)!=EOF){ 96 ac.clear(); 97 for (int i=0;i<n;i++){ 98 scanf("%s",s); 99 ac.insert(s); 100 } 101 ac.build(); 102 Matrix a=Matrix(ac.L); 103 for (int i=0;i<ac.L;i++) 104 for (int j=0;j<4;j++) 105 if (ac.end[ac.next[i][j]]==-1) 106 a.mx[i][ac.next[i][j]]++; 107 a=powm(a,m); 108 int ans=0; 109 for (int i=0;i<a.n;i++) 110 ans=(ans+a.mx[0][i])%MOD; 111 printf("%d\n",ans); 112 } 113 }
时间: 2024-10-03 19:02:21