DNA Sequence SCU3030 / poj2778 AC fail automata matrix pointer dp + Fast Power

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

M virus strings to ask how many different gene sequence of length n string does not contain the virus?

 

answer:

All viruses insert Tire AC tree automaton,

We Tire suffix tree node considered a mark containing a viral gene sequences

So when we build Fail pointer, if the pointer reaches the current local Fail suffix for the virus, then the current state otherwise unlawful

Then we can get a possibility of arriving matrix between states,

This matrix every time squaring, on behalf of adding a new suffix in which the answer is, we are asking the recursive

n is large, so you can quickly optimize power use

The final answer is, after multiplied by itself n times, all possible suffixes state and the first column

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define endl '\n'
#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;
}

 

Guess you like

Origin www.cnblogs.com/nervendnig/p/11233047.html