zoukankan      html  css  js  c++  java
  • 【AC自动机】【矩阵乘法】poj2778 DNA Sequence

    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;
    }
  • 相关阅读:
    图解JavaScript原型和原型链
    hash数组快速查找一个字符串中出现最多的字符,并统计出现的次数
    JS中数组和字符串的方法大全
    用js实现排列组合
    js中一个对象当做参数传递时候?
    用JavaScript按一定格式解析出URL 串中所有的参数
    从Object.definedProperty中看vue的双向数据的绑定
    Uncaught (in promise) TypeError:的错误
    vue之生命周期的一点总结
    原子性和原子性操作
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6498869.html
Copyright © 2011-2022 走看看