poj2778 ac自动机+矩阵

此题ac的我莫名其妙的的。。。

http://blog.csdn.net/kk303/article/details/6936046此blog说了比较要注意的地方

由于我的模版是数组模拟链表的。所以很多地方不像链表那样写起来顺畅,即链表一个个表示下去就可以了。那么我就要注意父与子的关系

此题非常要注意的一点建立失配边的时候需要将标记下放。在insert的时候如果当前串找到的是个坏的,那么就需要将其下标赋值为1,那么当建失配边的时候访问到的节点如果当前节点的父亲节点是下标为1的节点,那么当前节点也必须标记为1,这样标记下放。这个请看下面解析

此解析我参考至http://blog.henix.info/blog/poj-2778-aho-corasick-dp.html 我加了我自己的东西在里面

举个例子:{AG, CG} ,首先构造 AC 自动机:

给每个节点加了编号,只有 0 1 2 是合法的,其他状态到达就直接死了,不用处理。

  然后将上面的 AC 自动机转化成下面这张表:

这张表表示当前状态遇到一个字母后跳转到什么状态。我称之为“跳转表”,对应于我代码中的 jump 域。这个貌似跟传说中的“trie 图”类似,都是把自动机确定化。

  然后数一下每一行有多少个 0 ,多少个 1 ……将上表转化成下面的递推关系

其中 fi(n) 表示到第 n 步,有多少个字符串处于状态 i 。f0(n−1) 前面的系数 2 是 0 那一行包含的 0 的数量,表示如果上一步有一个处于状态 0 ,那么下一步就会有 2 个处于状态 0(分别对应遇到 T 和 G 的情况)。其他类似。

这里我想说明一下:当你计算到f0(2)的时候等于6,为什么呢,因为T往前加一个字母可以是A,C,T,G。G往前加一个字母可得A,C,G,T但是AG 和 CG就是6个 递推式子是怎么来的呢,是由于我从后往前增加字母,那么我在满足约束的情况下,往前增加。例如原来两个0那么任意其中一种我往前增加字母都可以每个增加两种情况,所以有4种,那么往前1或则加2(即A或者C)那么就的根据前者的那个条件来看情况数了,自己可以想想,这里我想了好久呢。

  将上面的系数矩阵提出来,立即得到:

这就是所谓“常系数线性递推式”,详见黑书练习题 2.1.8。比如对于 n = 3 ,先计算系数矩阵的 3 次方:

然后把结果矩阵的第一列加起来即得到答案 48 。

  题目中 n 可能非常大,这时就轮到快速幂运算出场了。使用快速幂运算,计算 An 的时间复杂度为 O(log n) 次乘法(此题是矩阵乘法)。


  最后,还要考虑一种情况,即有些疾病 DNA片段互相包含的情况,以 {ACG, C} 为例:

其中 C 是死节点,那么 AC(红色的)是不是呢?表面上看 AC 不是疾病片段,但实际上,匹配了 AC 就相当于匹配了 C ,所以 AC 也是死节点!

那么这里就是我前面最开始说的标记下放因为访问到AC的C时候C并不是标记了的,但是C其实已经是死节点了。那么我就对C标记其死节点。

最后实现我是用训练指南上的方法建立的。

但是次题我建立matrix的时候我自己都不知道怎么过 的。。。。我将最后一个字符串的标记作为第一行的矩阵,然后其他的就依次在第2到sz-1行

这样模糊的过掉了,求解释这一块啊







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值