首页 > 代码库 > Hdu 3962 Microgene (AC自动机+矩阵)
Hdu 3962 Microgene (AC自动机+矩阵)
题目大意:
构造一个串使得有两个以及两个以上的目标串。长度为L的所有串中有多少个这样的串。
思路分析:
用所有的数量减去只有1个和没有目标串的数量就是答案了。
如果数据很小,可以用dp解。dp[i][j][k] 表示长度为i,走到自动机的j,有k个目标串的数量。
转移便是。
if(j->next[d] ->isword) dp[i+1][j->next][1] += dp[i][j][0].
else dp[i+1][j->next][0]+=dp[i][j][0],dp[i+1][j->next][1] += dp[i][j][1]...
现在长度达到百万。
所以用矩阵优化。
设自动机的节点数量为idx,那么就开一个(2*idx,2*idx)的矩阵。
如果i<idx j<idx 表示 开始在i的时候没有目标串,走到j也没有。
如果i<idx j>idx 表示 开始在i的时候没有目标串,走到j有了一个。
后面同理。。。
那么构造这个矩阵便是按照上面的dp方程类似构造。
if(j->next[d]->isword)matrix [i][j->next->index+idx]++; 开始的时候没有,走过来加一个
else matrix [i][j]++,matrix [i+idx][j+idx] 开始的时候没有,走到j也没有 和 开始的时候有一个,走到j还是一个。
矩阵的构造是难= =
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define N 75 using namespace std; const int mod = 10007; const char tab = 'a'; const int max_next = 4; int rev[256]; struct trie { struct trie *fail; struct trie *next[max_next]; int isword; int index; }; struct AC { trie *que[100005],*root,ac[100005]; int head,tail; int idx; trie *New() { trie *temp=&ac[idx]; for(int i=0;i<max_next;i++)temp->next[i]=NULL; temp->fail=NULL; temp->isword=0; temp->index=idx++; return temp; } void init() { idx=0; root=New(); } void Insert(trie *root,char *word,int len){ trie *t=root; for(int i=0;i<len;i++){ if(t->next[rev[word[i]]]==NULL) t->next[rev[word[i]]]=New(); t=t->next[rev[word[i]]]; } t->isword++; } void acbuild(trie *root){ int head=0,tail=0; que[tail++]=root; root->fail=NULL; while(head<tail){ trie *temp=que[head++],*p; for(int i=0;i<max_next;i++){ if(temp->next[i]){ if(temp==root)temp->next[i]->fail=root; else { p=temp->fail; while(p!=NULL){ if(p->next[i]){ temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL)temp->next[i]->fail=root; } if(temp->next[i]->fail->isword)temp->next[i]->isword++; que[tail++]=temp->next[i]; } else if(temp==root)temp->next[i]=root; else temp->next[i]=temp->fail->next[i]; } } } void tra() { for(int i=0;i<idx;i++) { if(ac[i].fail!=NULL)printf("fail = %d ",ac[i].fail->index); for(int k=0;k<max_next;k++) printf("%d ",ac[i].next[k]->index); puts(""); } } }sa; struct matrix { int r,c; int data[N][N]; matrix(){} matrix(int _r,int _c):r(_r),c(_c){memset(data,0,sizeof data);} friend matrix operator * (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=B.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<B.c;j++) { for(int k=0;k<A.c;k++) { if(A.data[i][k] && B.data[k][j]){ res.data[i][j]+=A.data[i][k]*B.data[k][j]; res.data[i][j]%=mod; } } } } return res; } friend matrix operator + (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<A.c;j++) { res.data[i][j]=A.data[i][j]+B.data[i][j]; res.data[i][j]%=mod; } } return res; } friend matrix operator - (const matrix A,const matrix B) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++) { for(int j=0;j<A.c;j++) { res.data[i][j]=A.data[i][j]-B.data[i][j]; res.data[i][j]=(res.data[i][j]%mod+mod)%mod; } } return res; } friend matrix operator ^ (matrix A,int n) { matrix res; res.r=A.r;res.c=A.c; memset(res.data,0,sizeof res.data); for(int i=0;i<A.r;i++)res.data[i][i]=1; while(n) { if(n&1)res=res*A; A=A*A; n>>=1; } return res; } void print() { for(int i=0;i<r;i++) { for(int j=0;j<c;j++) printf("%d ",data[i][j]); puts(""); } } }E,zero; char word[30]; int main() { rev['A']=0; rev['C']=1; rev['G']=2; rev['T']=3; int n,L; while(scanf("%d%d",&n,&L)!=EOF) { sa.init(); for(int i=1;i<=n;i++) { scanf("%s",word); sa.Insert(sa.root,word,strlen(word)); } sa.acbuild(sa.root); E=matrix(sa.idx*2,sa.idx*2); for(int i=0;i<sa.idx*2;i++)E.data[i][i]=1; matrix origin=matrix(sa.idx*2,sa.idx*2); for(int i=0;i<sa.idx;i++) { for(int j=0;j<4;j++) { int temp=sa.ac[i].next[j]->index; if(sa.ac[i].next[j]->isword) origin.data[i][temp+sa.idx]++; else origin.data[i][temp]++,origin.data[i+sa.idx][temp+sa.idx]++; } } origin.print(); origin=origin^L; int ans=1; int x=4; int t=L; while(t) { if(t&1)ans=(ans*x)%mod; x=(x*x)%mod; t>>=1; } for(int i=0;i<2*sa.idx;i++) { ans-=origin.data[0][i]; ans=(ans+mod)%mod; } printf("%d\n",ans); } return 0; }
Hdu 3962 Microgene (AC自动机+矩阵)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。