POJ2778

 

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 a genetic disease. Until now scientists have found several those segments, the problem is how many kinds of DNA sequences of a species don't contain those segments.  

Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.  

Input

First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.  

Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.  

Output

An integer, the number of DNA sequences, mod 100000.

Sample Input

4 3
AT
AC
AG
AA

Sample Output

36

 

PKU2778   DNA Squence ccsu_010 原创

在A这道题之前,A了pku3691,跟这道题这不错,应该还比较难吧。这里是给定M个病毒DNA,求组成长度为N的DNA序列的个数,3691是在给定M个病毒之后,给定一个DNA序列,然后求最小修改几个字符可以使它不含病毒序列(AC自动机+dp)。

两道题都要注意,当某病毒片段为其子序列时,它也就会是危险序列。

这道题参考了AC大牛的博文。他构造的DFA给了我启发(之前什么都不懂,DFA什么意思都是AC大牛告诉的,在此3Q一下)。

虽然会建AC自动机,可是不知道怎么运用。

先看一下样例数据

4 3

AT

AC

AG

AA

我这里的自动机是基于静态trie的。按照常规方法建立就可以了,但还是要注意它的子串。假如我们建立了自动机,接下来就是如何构造矩阵了。先看上面的数据。虚线指向它的fail。红色为末结点,不能出现在生成的序列中。

 

 

图中有6个结点,代表6种状态,S0是起点,可以代表其它安全状态。它的son[T,C,G]为-1(空指针),如果在它后面加T,C,G肯定会是安全的。所以dp[n][0]=3*dp[n-1][0]+x; x表示可能其它状态会有转移到S0。dp[i][j]表示长为i后缀状态为j的DNA数。

在看S1,它的son[T,C,G,A]都不为 -1,当添加一个字符时,必然会到它的son[]的状态,不可能回到S0,所以上面的x=0(都不符合条件)。

S1 的son都有,但是却都是末结点——危险,不用回来了,则S1只能由S0+A得来。所以dp[n][1]= dp[n-1][0]; 其它都为0.

我们用矩阵g[i][j]表示:从第i个结点(状态)到第j个结点有g[i][j]种情况。

得到矩阵
,然后在求该矩阵的N次方,答案就是ans+=tot[0][i]。矩阵中3=『S0加一个字母到S0有三条路径,dp公式中不是×3了嘛』,1=『S0添加一个字母到S1只有一条路径,即+A』,前面分析了S1到S0是没有转移路径的,S1添加任何字母都会到他的son去。

 

这组数据太简单,再看一组,看fail是怎么运用的。

2 3

AG

CG





S0,S1,S2,S3,S4,可以看作插入后,存储的顺序。上图表示后缀加该字符转移到另一状态。我们按顺序从S0->S4考虑,当然危险的(S2,S4)就不用考虑了。

1.先看S0,它的son[T]和son[G]为-1,所以可以直接转移。G[i][0]+2  (i==0,2->T/G)。

2.S1,son[G]!=-1但是son[G].end>0,即危险,所以不要管。Son[A]= -1, 如果在S1后面加个A,是否会危险呢??因为它的son[A]=-1,所以我们只有看它的fail了,(根据AC自动机性质知,从根到它的fail的序列是它的最长后缀,如果Si.fail.son[A].end>0,那在S1后加A也会危险的),在这里,S1的fail为S0,而S0.son[A]就是S1,不为-1,而且S1.end==0,所以S1后面可以+A,S1.fail+A后回到S1,g[1][1]++,即S1可以回到本状态。同样的,对于每一结点Si(状态),它的AGCT四个后继都要分析,如果son[j]==-1(即空指针)我们就看它的fail.son[j]是否不为-1,直到S0,哪个son[j]不为-1,那么Si+[j代表的字符]就可以转移到 它的son[j]所在的结点。例如S1转到S1, 因为它的fail(也就是S0)的son[A]就是S1.   如果它的son[j]不为-1,我们直接往下看,如果它的son[j].end==0(不危险)那g[i][son[j]所在的位置]++;

第二个例子得到矩阵

即 dp[n][0] =2*dp[n-1][]+dp[n-1][1]+dp[n-1][3];

dp[n][1] =dp[n-1][1] + dp[n-1][1] + dp[n-1][3];

dp[n][3] =dp[n-1][0] + dp[n-1][1] + dp[n-1][3];其它的没必要算,都为0.

My code

下面就可以去pku1625~

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值