标签:scan 链表 seq log sum ++i names open poj2778
http://blog.csdn.net/morgan_xww/article/details/7834801
讲得很好~可以理解自动机的本质,就是一个用来状态转移的东西~对于确定的输入而言,可以从初始状态,按照转移边,转移到确定的终止状态。
而这种转移可以用矩乘加速。
#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> using namespace std; typedef long long ll; #define MOD 100000ll typedef vector<ll> vec; typedef vector<vec> mat; int N; mat I,A; mat operator * (const mat &a,const mat &b) { mat c(N,vec(N)); for(int i=0;i<N;++i) for(int j=0;j<N;++j) for(int k=0;k<N;++k) c[i][j]=(c[i][j]+a[i][k]*b[k][j]%MOD)%MOD; return c; } mat Quick_Pow(mat x,int p) { if(!p) return I; mat res=Quick_Pow(x,p>>1); res=res*res; if(p&1) res=res*x; return res; } queue<int>q; int child[110][4],fail[110],size=1,sum,ma[1111]; bool word[110]; void Insert(char S[]) { int len=strlen(S); int now=0; for(int i=0;i<len;++i) { if(!child[now][ma[S[i]]]) child[now][ma[S[i]]]=size++; now=child[now][ma[S[i]]]; } word[now]=1; } void build() { fail[0]=-1; q.push(0); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=0;i<4;++i) if(child[U][i]) { int V=fail[U]; while(V!=-1) { if(child[V][i]) { fail[child[U][i]]=child[V][i]; break; } V=fail[V]; } if(V==-1) fail[child[U][i]]=0; if(word[fail[child[U][i]]]) word[child[U][i]]=1;//如果某个单词是该结点所在单词的前缀,那么该结点也应被标记为单词结点 q.push(child[U][i]); } else if(U) child[U][i]=child[fail[U]][i];//当然你在dp过程中在Trie上跳也行,但这样就避免了重复计算 //由于BFS,其实形成了一个类似链表的结构 } } int m,n,ma2[110]; int main() { // freopen("poj2778.in","r",stdin); ma[‘A‘]=0; ma[‘G‘]=1; ma[‘C‘]=2; ma[‘T‘]=3; char s[13]; scanf("%d%d",&m,&n); for(int i=1;i<=m;++i) { scanf("%s",s); Insert(s); } build(); for(int i=0;i<size;++i) if(!word[i]) ma2[i]=N++; I.assign(N,vec(N)); for(int i=0;i<N;++i) I[i][i]=1; mat A(N,vec(N)); for(int i=0;i<size;++i) for(int j=0;j<4;++j) if((!word[i]) && (!word[child[i][j]])) ++A[ma2[i]][ma2[child[i][j]]]; // for(int i=0;i<N;++i) // { // for(int j=0;j<N;++j) // printf("%d ",A[i][j]); // puts(""); // } A=Quick_Pow(A,n); // for(int i=0;i<N;++i) // { // for(int j=0;j<N;++j) // printf("%d ",A[i][j]); // puts(""); // } ll ans=0; for(int i=0;i<N;++i) ans=(ans+A[0][i])%MOD; cout<<ans<<endl; return 0; }
【AC自动机】【矩阵乘法】poj2778 DNA Sequence
标签:scan 链表 seq log sum ++i names open poj2778
原文地址:http://www.cnblogs.com/autsky-jadek/p/6498869.html