zoukankan      html  css  js  c++  java
  • DNA Sequence SCU3030/poj2778 AC自动机fail指针dp+矩阵快速幂

    http://acm.scu.edu.cn/soj/problem.action?id=3030

    给m个病毒串,问多少种不同的长度为n的基因序列不包含病毒串?

    题解:

    把所有病毒插入AC自动机的Tire树中,

    我们把Tire树上的标记节点认为是一种包含了病毒的基因序列的后缀

    因此我们建立Fail指针的时候,如果当前Fail指针所到达的地方为病毒后缀,那么当前状态即为非法的

    然后我们可以在状态之间得到一个可否抵达的矩阵,

    这个矩阵每自乘一次,就代表加入一个新的后缀在其中,也就是答案所求的递推式了

    n很大,因此可以用快速幂优化

    最终答案就是,自乘n次后,第一列的所有可能的后缀状态的和

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #define endl '
    '
    #define ll long long
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pii pair<int,int>
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    #define forn(ii,x) for(int ii=head[x];ii;ii=e[ii].next)
    using namespace std;
    const int maxn=1e4+10,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    const ll mod=1e5;
    //const double PI=acos(-1.0);
    //head
    int casn,n,m;
    class matrix{public:
      int a,b;
      vector<vector<ll> > x;
      matrix(int _a=1,int _b=1):
        a(_a),b(_b),x(a,vector<ll>(b)){}
      void element(int n){
        a=b=n;x=matrix(n,n).x;
        for(int i=0;i<n;i++)x[i][i]=1;
      }
      void fill(ll xx=0){
        for(int i=0;i<a;i++)for(int j=0;j<b;j++)
          x[i][j]=xx;
      }
      void fill(vector<vector<ll> > &y){
        x=y;a=y.size();b=y[0].size();
      }
      matrix operator *(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<m.b;j++)
          for(int k=0;k<b;k++)if(x[i][k]&&m.x[k][j])
            ans.x[i][j]=(ans.x[i][j]+(x[i][k]*m.x[k][j]%mod+mod))%mod;
        return ans;
      }
      matrix operator +(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<b;j++)
            ans.x[i][j]=(x[i][j]+m.x[i][j]+mod)%mod;
        return ans;
      }
      matrix operator -(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<b;j++)
          ans.x[i][j]=(x[i][j]-m.x[i][j]+mod)%mod;
        return ans;
      }
      matrix pow(ll p){
        matrix ans,t;ans.element(a);t.fill(x);
        while(p){if(p&1) ans=t*ans;t=t*t;p>>=1;}
        return ans;
      }
    };
    const int csize=4,minc=0;
    class autom{public:
    #define nd node[now]
      struct acnode{int flag,son[csize],fail;}node[maxn];
      int cnt;
      queue<int> que;
      void clear(){
        memset(node,0,sizeof node);
        cnt=0;
      }
      void insert(char *s,int len=0){
        if(!len)len=strlen(s);
        int now=0;
        rep(i,0,len-1){
          int ch=s[i]-minc;
          if(!nd.son[ch]) nd.son[ch]=++cnt;
          now=nd.son[ch];
        }
        nd.flag=1;
      }
      void init(){
        int now=0;
        rep(i,0,csize-1) if(nd.son[i]) que.push(nd.son[i]);
        while(!que.empty()){
          now=que.front();que.pop();
          rep(i,0,csize-1){
            if(nd.son[i]) {
              node[nd.son[i]].fail=node[nd.fail].son[i];
              que.push(nd.son[i]);
            }else nd.son[i]=node[nd.fail].son[i];
            node[nd.son[i]].flag|=node[node[nd.fail].son[i]].flag;
          }
        }
      }
    }acam;
    char p[1010];
    int main(){IO;
      ll n,m;
      while(cin>>m>>n){
        acam.clear();
        rep(i,1,m) {
          cin>>p;
          int l=strlen(p);
          rep(j,0,l-1){
            if(p[j]=='A') p[j]=0;
            else if(p[j]=='C') p[j]=1;
            else if(p[j]=='G') p[j]=2;
            else p[j]=3;
          }
          acam.insert(p,l);
        }
        acam.init();
        int mt=acam.cnt;
        vector<vector<ll> > _f(mt+1,vector<ll>(mt+1));
        rep(i,0,mt){
          if(acam.node[i].flag) continue;
          rep(j,0,3) if(!acam.node[acam.node[i].son[j]].flag)
            _f[i][acam.node[i].son[j]]++;
        }
        matrix f;f.fill(_f);
        f=f.pow(n);
        ll ans=0;
        rep(i,0,mt) ans=(ans+f.x[0][i])%mod;
        cout<<ans<<endl;
      }
      return 0;
    }
    
  • 相关阅读:
    Android实战——第三方服务之Bmob后端云的集成、用户登陆、用户注册、获取用户、用户注销(一)
    Android实战——第三方服务之Bmob后端云的答题系统小项目(四)
    10.Python运行Scrapy时出现错误: ModuleNotFoundError: No module named 'win32api'
    基础小知识(1)
    9.Python安装scrapy教程
    1.使用Fiddler进行接口测试
    8.Python编写登录接口
    18.Selenium+Python案例 -- 豆瓣
    17.Selenium+Python日期控件小案例
    16.Selenium+Python关于句柄的小Demo
  • 原文地址:https://www.cnblogs.com/nervendnig/p/11233047.html
Copyright © 2011-2022 走看看