[POJ2778]DNA Sequence

  看到n<=20亿顿时傻眼。。AC自动机上用矩阵乘法优化DP。。。sxbk

  建出AC自动机,把非法的节点去掉后求出trie图。。。

  然后根据trie图中的转移关系建矩阵。。。。最后跑个快速幂

  竟然搞出来了...感人肺腑

  脑子各种短路。。先是矩乘打挂,然后是trie图求措TAT。调了一整节晚自修。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int modd=100000;
 8 int v[257],dl[103],fail[103],num[103];
 9 int ch[103][4],tot,next[103][4];
10 ll mp[103][103],cnt;
11 ll c[103][103],tmp[103][103],ans;
12 int i,j,k,n,m,l,r;
13 bool gg[103];
14 char s[23];
15
16 inline void trie(int n){
17     int i,p=0;
18     for(i=0;i<n;i++){
19         if(!ch[p][v[s[i]]])ch[p][v[s[i]]]=++tot,p=tot;
20         else p=ch[p][v[s[i]]];
21     }
22     gg[p]=1;//printf("gg:  %d\n",p);
23 }
24 inline void getfail(){
25     int l=0,r=1,i,j,now,p;dl[1]=0;
26     while(l<r){
27         now=dl[++l];//printf("   %d  fail:%d    gg:%d\n",now,fail[now],gg[now]);
28         for(i=0;i<4;i++)if(ch[now][i]){
29             j=ch[now][i];//printf("  %d-->%d\n",now,j);
30             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
31             if(!now)fail[j]=0;else fail[j]=ch[p][i];
32             dl[++r]=j;gg[j]|=gg[fail[j]];
33         }
34     }
35 }
36 inline void getnext(){
37     l=0,r=1;int i,now,p;dl[1]=0;
38     bool flag=0;
39     while(l<r){
40         now=dl[++l];//printf("    %d\n",now);
41         for(i=0;i<4;i++){
42             if(ch[now][i]){
43                 if(gg[ch[now][i]])next[now][i]=-1;
44                 else next[now][i]=ch[now][i],dl[++r]=ch[now][i];
45             }
46             else{
47                 for(p=fail[now];p&&!ch[p][i];p=fail[p]);
48                 next[now][i]=gg[ch[p][i]]?-1:ch[p][i];
49             }
50         //    printf("%d %d  next:%d\n",now,i,next[now][i]);
51         }
52     }
53 }
54 inline void upd(){
55     cnt=0;int i,j;
56     for(i=1;i<=r;i++)
57         num[dl[i]]=++cnt;
58     for(i=1;i<=r;i++){
59         j=dl[i];
60         for(k=0;k<4;k++)if(next[j][k]!=-1)
61             mp[num[next[j][k]]][num[j]]++;
62     }
63
64 //    for(i=1;i<=r;puts(""),i++)
65 //        for(j=1;j<=r;j++)printf("   %lld",mp[i][j]);
66 }
67
68
69 inline void multoc(){
70     register int i,j,k;
71     for(i=1;i<=cnt;i++)
72     for(j=1;j<=cnt;tmp[i][j]%=modd,j++)
73         for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*c[k][j];
74     for(i=1;i<=cnt;i++)memcpy(c[i],tmp[i],(cnt+1)<<3);
75 }
76 inline void multomp(){
77     register int i,j,k;
78     for(i=1;i<=cnt;i++)
79     for(j=1;j<=cnt;tmp[i][j]%=modd,j++)
80         for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*mp[k][j];
81     for(i=1;i<=cnt;i++)memcpy(mp[i],tmp[i],(cnt+1)<<3);
82 }
83 int main(){
84     v[‘A‘]=0,v[‘C‘]=1,v[‘G‘]=2,v[‘T‘]=3;
85
86     scanf("%d%d",&n,&m);
87     for(i=1;i<=n;i++)scanf("%s",s),trie(strlen(s));
88     getfail(),getnext(),upd();
89     for(i=1;i<=cnt;i++)c[i][i]=1;
90
91     while(m){
92         if(m&1)
93             multoc();
94         m>>=1;if(m)multomp();
95     }
96     for(i=1,ans=0;i<=cnt;i++)ans=(ans+c[i][1])%modd;
97     printf("%lld\n",ans);
98     return 0;
99 }

时间: 2024-10-20 22:44:16

[POJ2778]DNA Sequence的相关文章

poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19991   Accepted: 7603 Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For ex

POJ2778 DNA Sequence Trie+矩阵乘法

题意:给定N个有A C G T组成的字符串,求长度为L的仅由A C G T组成的字符串中有多少个是不含给定的N个字符串的题解: 首先我们把所有的模式串(给定的DNA序列)建Trie,假定我们有一个匹配串,并且在匹配过程到S[i]这个字符时匹配到了Trie上的某个节点t,那么有两种可能: 匹配失败:t->child[S[i]]为空,跳转到t->fail,因此t->fail一定不能是某个模式串的结尾: 匹配成功:跳转到t->child[S[i+1]],因此t->child[S[i

【AC自动机】【矩阵乘法】poj2778 DNA Sequence

http://blog.csdn.net/morgan_xww/article/details/7834801 讲得很好~可以理解自动机的本质,就是一个用来状态转移的东西~对于确定的输入而言,可以从初始状态,按照转移边,转移到确定的终止状态. 而这种转移可以用矩乘加速. #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> us

POJ2778 DNA Sequence AC自动机上dp

网址:https://vjudge.net/problem/POJ-2778 题意: 给出字符集${A,C,G,T}$和一些字符串(长度不超过$10$,且数量不超过$10$个),求长度为$n(n \leq 2e9)$的字符串中不包括上面这些字符串的字符串的数量. 题解: 我们可以先考虑一种方式:设$dp(i,j)$是用了$i$个字符拼出符合题意的长度为$j$的字符串的数量,在本题中$dp(i,j)=\sum _{j' \subseteq j} dp(i-1,j')$,显然时间复杂度是指数级的,不

[POJ2778]DNA Sequence(AC自动机 + DP + 矩阵优化)

传送门 AC自动机加DP就不说了 注意到 m <= 10,所以模式串很少. 而 n 很大就需要 log 的算法,很容易想到矩阵. 但是该怎么构建? 还是矩阵 A(i,j) = ∑A(i,k) * A(k,j),那么i到j的方案数就是j到k的方案数称k到j的方案数,那么直接矩阵快速幂即可 #include <queue> #include <cstdio> #include <cstring> #define N 100001 #define p 100000 #d

[poj2778]DNA Sequence(AC自动机+矩阵快速幂)

解题关键:卡时限过的,正在找原因中. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<queue> 8 using namespace std; 9 typedef long long ll; 10 cons

DNA Sequence(POJ2778 AC自动机dp+矩阵加速)

传送门 DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K       Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequenc

【POJ】2278 DNA Sequence

各种wa后,各种TLE.注意若AC非法,则ACT等一定非法.而且尽量少MOD. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 #define MAXN 105 8 #define NXTN 4 9 10 char str[15]; 11 12 typedef struct Matrix {

hdu 1560 DNA sequence(迭代加深搜索)

DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 15   Accepted Submission(s) : 7 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description The twenty-first century