【POJ2778】DNA Sequence(AC自动机)

题意:

生物课上我们学到,DNA序列中只有A, C, T和G四种片段。

经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段”ATC”是不好片段,则”AGATCC”, “CATCAA”, “ATCATC”都是不好的DNA序列,这些不好片段我们可以称为病毒片段

现在已知m个病毒片段, 问长度为n的DNA序列,有多少种可能不包含病毒片段。答案可能很大,取模 100000。

【数据规模和约定】

0<=m<=10  病毒片段长度不超过10,只含A,T,C,G字母

1<=n<=2000000000

思路:AC自动机

因为fail[i]一定是i的一个前缀的后缀,fail[i]如果带病毒i必定带病毒

转移:

 {

    dp[0,1]:=1;

  for i:=1 to m do

  for eachedge(i,j)

  begin

   dp[i,j]:=dp[i,j]+dp[i-1,i];

  end;              }

用矩阵乘法优化

  1 const mo=100000;
  2 type arr=array[1..110,1..110]of int64;
  3 var y,c,ans,d:arr;
  4     s:array[1..4]of char;
  5     map:array[1..10000,‘A‘..‘Z‘]of longint;
  6     f,b,q:array[1..200000]of longint;
  7     m,n,i,j,k,t,sum,num:longint;
  8     ch:string;
  9
 10 procedure build;
 11 var i,k,d:longint;
 12 begin
 13  k:=1; d:=length(ch);
 14  for i:=1 to d do
 15  begin
 16   if map[k,ch[i]]=0 then begin inc(num); map[k,ch[i]]:=num; end;
 17   k:=map[k,ch[i]];
 18  end;
 19  b[k]:=1;
 20 end;
 21
 22 procedure acauto;
 23 var t,w,i,u,p,son:longint;
 24 begin
 25  t:=0; w:=1; q[1]:=1;
 26  while t<w do
 27  begin
 28   inc(t); u:=q[t];
 29   for i:=1 to 4 do
 30    if map[u,s[i]]>0 then
 31    begin
 32     son:=map[u,s[i]];
 33     p:=f[u];
 34     if u=1 then f[son]:=1
 35      else f[son]:=map[p,s[i]];
 36     inc(w); q[w]:=son;
 37    end
 38     else
 39     begin
 40      p:=f[u];
 41      if u=1 then map[u,s[i]]:=1
 42       else map[u,s[i]]:=map[p,s[i]];
 43     end;
 44  end;
 45 end;
 46
 47 begin
 48  assign(input,‘poj2778.in‘); reset(input);
 49  assign(output,‘poj2778.out‘); rewrite(output);
 50  readln(m,n);
 51  num:=1;
 52  s[1]:=‘A‘; s[2]:=‘C‘; s[3]:=‘G‘; s[4]:=‘T‘;
 53  for i:=1 to m do
 54  begin
 55   readln(ch);
 56   build;
 57  end;
 58  acauto;
 59  for i:=2 to num do
 60   if b[f[i]]=1 then b[i]:=1;
 61
 62  for i:=1 to num do
 63   if b[i]=0 then
 64    for j:=1 to 4 do
 65     if b[map[i,s[j]]]=0 then inc(d[i,map[i,s[j]]]);
 66
 67  t:=n;
 68  for i:=1 to num do ans[i,i]:=1;
 69  y:=d;
 70  while t>0 do
 71  begin
 72   if t and 1=1 then
 73   begin
 74    for i:=1 to num do
 75     for j:=1 to num do c[i,j]:=0;
 76    for i:=1 to num do
 77     for k:=1 to num do
 78     begin
 79      for j:=1 to num do c[i,k]:=c[i,k]+ans[i,j]*y[j,k];
 80      c[i,k]:=c[i,k] mod mo;
 81     end;
 82    for i:=1 to num do
 83     for j:=1 to num do ans[i,j]:=c[i,j];
 84   end;
 85   for i:=1 to num do
 86    for j:=1 to num do c[i,j]:=0;
 87   for i:=1 to num do
 88    for k:=1 to num do
 89    begin
 90     for j:=1 to num do c[i,k]:=c[i,k]+y[i,j]*y[j,k];
 91     c[i,k]:=c[i,k] mod mo;
 92    end;
 93   for i:=1 to num do
 94    for j:=1 to num do y[i,j]:=c[i,j];
 95   t:=t>>1;
 96  end;
 97  for i:=1 to num do sum:=(sum+ans[1,i]) mod mo;
 98  writeln(sum);
 99
100
101  close(input);
102  close(output);
103 end.
时间: 2024-12-23 12:32:37

【POJ2778】DNA Sequence(AC自动机)的相关文章

[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

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

首先建立Trie和失败指针,然后你会发现对于每个节点 i 匹配AGCT时只有以下几种情况: i 节点有关于当前字符的儿子节点 j 且安全,则i 到 j找到一条长度为 1的路. i 节点有关于当前字符的儿子节点 j 且 不安全,则i 到 j没有路. i 节点没有关于当前字符的儿子节点 但是能通过失败指针找到一个安全的节点j,那么 i 到 j 找到一条长度为1的路. 关于节点安全的定义: 当前节点不是末节点且当前节点由失败指针指回跟节点的路径上不存在不安全节点,那么这个节点就是安全节点. 然后问题就

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

题目链接:poj 2778 DNA Sequence 题目大意:给定一些含有疾病的DNA序列,现在给定DNA长度,问有多少种不同的DNA序列是健康的. 解题思路:对DNA片段建立AC自动机,因为最多10个串,每个串最长为10,所以最多可能有100个节点,在长度为n时 以每个节点终止的健康字符串个数形成一个状态集,通过AC自动机形成的边可以推导出n+1的状态集,走到单词节点是 非法的,所以同样的我们可以先走到单词节点,但是从单词节点不向后转移.这样可以构造一个矩阵,剩下的就是矩阵 快速幂.注意的一

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')$,显然时间复杂度是指数级的,不

POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

题意:给定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 #defin

Poj 2778 DNA Sequence (AC自动机+矩阵)

题目大意: 给出N个串,问在长度为L的所有串中,不包含任一已知串的个数有多少个. 思路分析: 已知一个矩阵A,A[i][j] 表示 节点i 到 节点 j 有一条变可以到达的方法数. 那么A^2 ,这个矩阵的 [i][j] 就代表这个节点 i 到节点 j 有两条边可以到达的方法数. 那么知道这个结论,我们要做的就是求一个节点到另外一个节点,要经过L条变(对应这长度为L的单词),而又要满足任意一条边都不能经过已知单词. 所以我们要用到ac自动机处理出所有已知的单词,在ac自动机上得到这个矩阵,使得任

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(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自动机+矩阵)

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 sequence contains segment ATC then it may mean that the animal may have

poj 1699 Best Sequence(AC自动机+状压DP)

题目链接:poj 1699 Best Sequence 题目大意:给定N个DNA序列,问说最少多长的字符串包含所有序列. 解题思路:AC自动机+状压DP,先对字符串构造AC自动机,然后在dp[s][i]表示匹配了s,移动到节点i时候的最短步数. #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <iostream> #include &