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

来源:互联网 发布:在淘宝好评返现违规吗 编辑:程序博客网 时间:2024/06/07 00:11

大神附图的题解:http://blog.csdn.net/morgan_xww/article/details/7834801

【题解】

将所有病毒串建立成字典树,并标记词尾结点,以下称"非法结点"


那么,我们希望改造一下这棵树,即删掉一些结点,构造一些有向边,使得一个n位字符串相当于从改造图的根走n步,且中途不会形成非法串 
对于树上的某个结点u,先允许它走到非法结点,将所有有向边都连好后,再将这些点删去 
若 v=ch[u][i] 存在,那么一种情况是从u走到v即可,
若v不存在,不代表不能走,可以求出失配函数,将u与f[u]等价,看ch[f[u][i]是否存在,

方便起见,使用改进过的AC自动机,这样,任意ch[u][i]都存在,若ch[u][i]==0(从root到v构成的串没有后缀是病毒串),那就用root代表u的下一个字母v 。

直接将u到ch[u][i]连边 
然后标记剩下非词尾的非法节点,由于字符串s_1~f[n]是串s_1~n的后缀,所以,若f[n]被标记,则n也应被标记,这保证了若s_i~n为病毒串,一定可以被标记 

对于有向图上走n步的问题,用邻接矩阵来处理 
我们构造这样一个邻接矩阵,若u->v存在,且u,v均合法,则A[u][v]++,这样,A[u][v]就代表u走一步到v有几种方式,且不可能形成非法串 
将矩阵A自乘n次,A[u][v]就代表u走n步到v有几种方式 
然后,以root为起点,枚举终点,累加答案即可 


【代码】

#include<stdio.h>#include<stdlib.h>#include<string.h>#define MOD 100000lltypedef long long LL;int ch[105][10],no[105],f[105],q[105],num[105];char s[15];int sz=0,L;struct juzhen{LL s[105][105];juzhen(){memset(s,0,sizeof(s));}};juzhen A;juzhen cheng(juzhen a,juzhen b){juzhen res;int i,j,k;for(i=1;i<=L;i++)for(j=1;j<=L;j++){for(k=1;k<=L;k++)res.s[i][j]+=a.s[i][k]*b.s[k][j];res.s[i][j]%=MOD;}return res;}juzhen ksm(juzhen a,int n){juzhen ans;if(n==1) return a;ans=ksm(a,n/2);ans=cheng(ans,ans);if(n&1) ans=cheng(ans,a);return ans;}void tj(){int u=0,len=strlen(s),i;for(i=0;i<len;i++){if(s[i]=='A') s[i]=1;if(s[i]=='T') s[i]=2;if(s[i]=='C') s[i]=3;if(s[i]=='G') s[i]=4;if(ch[u][s[i]]==0) ch[u][s[i]]=++sz;u=ch[u][s[i]];}no[u]=1;}void build(){int head=0,tail=0,i,u,v;for(i=1;i<=4;i++)if(ch[0][i]>0) q[tail++]=ch[0][i];while(head<tail){u=q[head++];no[u]|=no[f[u]];for(i=1;i<=4;i++){v=ch[u][i];if(v>0){q[tail++]=v;f[v]=ch[f[u]][i];}else ch[u][i]=ch[f[u]][i];}}}void get_jz(){int i,j;for(i=0;i<=sz;i++)if(no[i]==0) num[i]=++L;for(i=0;i<=sz;i++)if(no[i]==0)for(j=1;j<=4;j++)if(no[ch[i][j]]==0) A.s[num[i]][ num[ch[i][j]] ]++;}int main(){int n,m,i,ans=0;scanf("%d%d",&m,&n);for(i=1;i<=m;i++){scanf("%s",s);tj();}build();get_jz();A=ksm(A,n);for(i=0;i<=sz;i++)if(num[i]>0) ans+=A.s[num[0]][num[i]];printf("%d",ans%MOD);return 0;}


0 0
原创粉丝点击