AC自动机小试 POJ2778
来源:互联网 发布:电脑软件怎么清除数据 编辑:程序博客网 时间:2024/05/18 03:39
http://poj.org/problem?id=2778
题目翻译:给定m个异常基因片段,在所有长度为N的DNA序列中如‘AAAAA....’,'ATTTTT....','ATCG...','CGTA...',.....中不包含异常序列的DNA个数mod 100000(十万)的值
这题题解是AC自动机和矩阵乘法,首先建立AC自动机
我们先看AC自动机建立过程(会的跳过,不会的英语好的看这篇英文论文:http://wenku.baidu.com/view/8b6f6d85ec3a87c24028c467.html,不会的英文不好的看不懂论文的往下看)
首先定义node为记录类型
{ son[1..4]of int;code:char;fail:longint;danger:boolean;
son,fail初始为-1或nil或null,danger:=false;
}
定义函数
function anti(a:char):longint;
begin case a of
'A':exit(1);
'C':exit(2);
'G':exit(3);
'T':exit(4);
end;
end;
1.建立Trie树,即字母树
2.初始化第一层节点fail指针为root节点,将第一层节点加入队列中
3.取队首元素x,将所有x的son入队
4.for y ∈ x.son
begin
temp:=x.fail;
while (temp>0)or(temp<>root) do
begin
for z ∈ temp.son
if z.code=y.code
then flag:=true,break;
if flag then temp:=z,break;
temp:=temp.fail;
end;
if temp=root
then
for z ∈ root.son
if z.code=y.code
then temp:=z,break;
y.fail:=temp;
end;
5.Complete Build AC Automaton
注意到一个经典的矩阵乘法题,给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
答案是将有向图的邻接矩阵乘k次输出G[A,B]
我们可以把A点看做root点,走n步不经过异常节点的方案数mod p(p=100000)的值
那么很明显一点是x节点的son中的异常节点(设为y)是不可能由x转移到的
题中每个节点最多有4个son
如果某个x.son为nil呢
设z=x.fail,当前son为i
由于x.fail为x.son匹配失败时的最长后缀在trie中的位置,那么以fail指针往上(fail指针总是指向上面)寻找z.son[i]不为nil的z节点后终止
然后判断z.son[i]是否为异常节点,不是则g[x,z.son[i]]++或者若z=root且root.son[i]=nil 则g[x,root]++;
按照trie的bfs序列
取当前元素x
for i:=1 to 4 do
if x.son[i]=-1
then
begin
z:=x.fail
while (z<>root)and(z.son[i]=-1) do
z:=z.fail;
if (z=root)and(root.son[i]=-1)
then g[x,root]++
else
if (z.son[i]<>-1)and(not z.son[i].danger)
then g[x,z.son[i]]++;
end
else if not x.son[i].danger then g[x,x.son[i]]++;
然后就是将g矩阵乘n次,将第root行加起来mod 100000 就是ans
代码pascal
program poj2778;type matrix=array[0..101,0..101]of int64;const mo=100000;var a:string;nodes,leng,i,j,point,m,n,top,x,tail,som,k:longint;ans:int64; b,g:matrix; son:array[0..101,0..4]of longint; off:array[0..101]of longint; code:array[0..101]of char; stack:array[0..110]of longint; comp:array[0..110]of boolean;procedure muti(a,b:matrix;var c:matrix);begin fillchar(c,sizeof(c),0); for i:=0 to nodes do for j:=0 to nodes do begin for k:=0 to nodes do c[i,j]:=(a[i,k]*b[k,j]+c[i,j])mod mo; end;end;function anticode(a:char):longint;begin case a of 'A':exit(1); 'C':exit(2); 'G':exit(3); 'T':exit(4); else exit(0); end;end;begin readln(m,n); fillchar(son,sizeof(son),$ff); for i:=1 to m do begin readln(a); leng:=length(a); point:=0; for j:=1 to leng do begin if son[point,anticode(a[j])]<>-1 then point:=son[point,anticode(a[j])] else begin inc(nodes); son[point,anticode(a[j])]:=nodes; code[nodes]:=a[j]; point:=nodes; end; end; comp[point]:=true; end; top:=0; tail:=1; while top<tail do begin inc(top); x:=stack[top]; for i:=1 to 4 do if son[x,i]<>-1 then begin inc(tail); stack[tail]:=son[x,i]; if x=0 then continue; som:=off[x]; repeat if son[som,i]<>-1 then begin som:=son[som,i]; break; end; som:=off[som]; until som<=0; if som=0 then if son[som,i]<>-1 then som:=son[som,i]; if comp[som] then comp[son[x,i]]:=true; off[son[x,i]]:=som; end; end; top:=0;nodes:=0; while top<tail do begin inc(top); x:=stack[top]; if comp[x] then continue; if x>nodes then nodes:=x; for i:=1 to 4 do if son[x,i]=-1 then begin som:=off[x]; while (som>0)and(son[som,i]=-1) do begin som:=off[som]; end; if (son[som,i]<>-1)and(not comp[son[som,i]]) then inc(g[x,son[som,i]]) else if (som=0)and(son[som,i]=-1) then inc(g[x,0]); end else if (son[x,i]<>-1)and(not comp[son[x,i]]) then inc(g[x,son[x,i]]); end; for i:=0 to nodes do b[i,i]:=1; while (n>0) do begin if (n and 1)>0 then muti(b,g,b); n:=n>>1; muti(g,g,g); end; for i:=0 to nodes do ans:=(ans+b[0,i])mod mo; writeln(ans);end.
另一篇题解:http://hi.baidu.com/%D2%D5%C1%D6010/blog/item/6db06ccf0a3b440993457e7b.html
- AC自动机小试 POJ2778
- POJ2778 AC自动机 + 矩阵
- poj2778 ac自动机+矩阵
- POJ2778-AC自动机+矩阵
- AC自动机+DP(POJ2778&&POJ3691)
- POJ2778 AC自动机经典题
- poj2778之AC自动机+矩阵快速幂
- AC自动机构造字符串(好)poj2778
- poj2778(AC自动机+矩阵快速幂)
- 【POJ2778】AC自动机,DP,矩阵乘法
- poj2778 AC自动机+矩阵快速幂
- poj2778--DNA Sequence(AC自动机+矩阵优化)
- POJ2778---DNA Sequence(AC自动机+矩阵)
- poj2778 & hdu 2243 AC自动机+矩阵 &&BZOJ2938
- 【AC自动机】hdu2222 hdu2896 hdu3065 zoj3430 poj2778
- AC自动机简单题 hdu2222+poj2778
- poj2778 DNA Sequence AC自动机+矩阵乘法
- poj2778--DNA Sequence(AC自动机+矩阵优化)
- atlab中的数值取整
- 响应者和响应者链
- OO-ALV 弹出窗口
- chrome技术资料整理,随时更新
- ASP.NET 实现伪静态网页方法
- AC自动机小试 POJ2778
- getElementsByName 的疏忽
- JSP网页如何连接数据库?
- Linux驱动开发 -- 打开dev_dbg()
- 手机锁解锁方法
- nginx sub_filter 选项
- com.opensymphony.xwork2.spring.SpringObjectFactory.getClassInstance
- YouTube 的架构扩展
- 自建表格及表格维护生成器