poj 2778 DNA Sequence AC自动机+矩阵快速幂

题意:给定M个疾病DNA序列,求组成长度为N的DNA序列的个数,其字串不含疾病DNA,答案模100000。

 

思路:AC自动机+矩阵快速幂

先建自动机,注意某给定的疾病DNA序列是另一疾病DNA序列的子串的情况。 这种情况可以在建立失败链接的时候搞定。

之后自动机上 每一个节点作为一个状态,总共node_num个状态node_num<=101。

题目可以转换在一个有向图里,从i开始走k步一共有多少条路径。答案是有向图的邻接矩阵的k次方 输出G[i][1]+……+G[i][n]

建立一个node_num*node_num 的矩阵 进行矩阵快速幂 具体转化详见http://hi.baidu.com/%D2%D5%C1%D6010/blog/item/6db06ccf0a3b440993457e7b.htm

  1 #include<iostream>
2 #include<map>
3 #include<cstring>
4 using namespace std;
5 #define MAXM 110
6 #define mod 100000
7 struct node
8 {
9 int name;
10 int id;
11 node *next[5];
12 node *failink;
13 node *father;
14 bool end;
15 node()
16 {
17 end=0;
18 memset(next,0,sizeof(next));
19 }
20 };
21 struct matrix
22 {
23 long long a[MAXM][MAXM];
24 matrix()
25 {
26 memset(a,0,sizeof(a));
27 }
28 };
29 node *head;
30 node memo[MAXM];
31 node *f[MAXM];
32 int node_num=0;
33 int top=0;
34 node *Q[MAXM];
35 matrix G;
36 int m,n;
37 matrix operator *(const matrix &x,const matrix &y)
38 {
39 int i,j,k;
40 matrix ans;
41 for(i=1;i<=node_num;i++)
42 for(j=1;j<=node_num;j++)
43 for(k=1;k<=node_num;k++)
44 {
45 ans.a[i][j]+=x.a[i][k]*y.a[k][j];
46 if(ans.a[i][j]>=mod) ans.a[i][j]%=mod;
47 }
48 return ans;
49 }
50 int get(char c)
51 {
52 switch(c)
53 {
54 case 'A':return 1;
55 case 'G':return 2;
56 case 'C':return 3;
57 case 'T':return 4;
58 }
59 }
60 void insert(node *t,char c[],int i)
61 {
62 if(i==strlen(c))
63 {
64 t->end=1;
65 return ;
66 }
67 int x=get(c[i]);
68 if(t->next[x]==NULL)
69 {
70 node *p=&memo[top++];
71 p->name=x; p->father=t; p->id=++node_num; f[node_num]=p;
72 t->next[x]=p;
73 }
74 insert(t->next[x],c,i+1);
75 }
76 void set_fail_link()
77 {
78 int i,j;
79 node *p,*t;
80 int front,tail;
81 Q[front=tail=1]=head;
82 while(front<=tail)
83 {
84 p=Q[front++];
85 if(p->father==head) p->failink=head;
86 else if(p!=head)
87 {
88 t=p->father->failink;
89 while(1)
90 {
91 if(t->next[p->name]!=NULL)
92 {
93 if(t->next[p->name]->end) p->end=1; //子串中有疾病DNA序列的情况
94 p->failink=t->next[p->name];
95 break;
96 }
97 else if(t==head)
98 {
99 p->failink=t;
100 break;
101 }
102 else t=t->failink;
103 }
104 }
105 for(i=1;i<=4;i++)
106 if(p->next[i]!=NULL) Q[++tail]=p->next[i];
107 }
108 }
109 void build_matrix()
110 {
111 int i,j;
112 for(i=1;i<=node_num;i++)
113 if(!f[i]->end)
114 for(j=1;j<=4;j++)
115 {
116 if(f[i]->next[j]!=NULL&&f[i]->next[j]->end==0)
117 G.a[i][f[i]->next[j]->id]++;
118 else if(f[i]->next[j]==NULL)
119 {
120 if(i==0) G.a[0][0]++;
121 else
122 {
123 node *p=f[i];
124 while(p->next[j]==NULL)
125 {
126 if(p->id==1) break;
127 p=p->failink;
128 }
129 if(p->next[j]!=NULL&&p->next[j]->end==0)
130 G.a[i][p->next[j]->id]++;
131 else if(p->id==1&&p->next[j]==NULL)
132 G.a[i][1]++;
133 }
134 }
135 }
136 }
137 int matrix_pow(int n)
138 {
139 matrix ans;
140 int i,j;
141 for(i=1;i<=node_num;i++) ans.a[i][i]=1;
142 while(n>0)
143 {
144 if(n&1) ans=ans*G;
145 G=G*G;
146 n>>=1;
147 }
148 long long sum=0;
149 for(i=1;i<=node_num;i++)
150 sum+=ans.a[1][i];
151 return sum%mod;
152 }
153
154 int main()
155 {
156 char c[11];
157 scanf("%d%d",&m,&n);
158 head=&memo[top++]; head->father=NULL;
159 head->id=++node_num; f[1]=head;
160 int i,j;
161 for(i=1;i<=m;i++)
162 {
163 scanf("%s",c);
164 insert(head,c,0);
165 }
166 set_fail_link();
167 build_matrix();
168 printf("%d\n",matrix_pow(n));
169 system("pause");
170 return 0;
171 }


l
                                                                                           

原文地址:https://www.cnblogs.com/myoi/p/2344480.html