DNAシークエンスSCU3030 / poj2778 ACは、オートマトンの行列ポインタDP +高速電力を失敗します

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

Mウイルスの文字列は、ウイルスが含まれていない長さnの文字列のどのように多くの異なる遺伝子配列を依頼するには?

 

ソリューション:

すべてのウイルスは、タイヤACツリーオートマトンを挿入し、

我々はタイヤ接尾辞木のノードは、ウイルス遺伝子配列を含むマークを検討し

ポインタは、その後、現在の状態それ以外の違法なウイルスのための現在のローカル失敗サフィックスに到達したのであれば、私たちは、失敗のポインタをビルドするとき

その後、我々は状態の間で行列に到着する可能性を得ることができ、

この行列乗たびに、答えはである新しいサフィックスを追加することに代わって、私たちは、再帰を求めています

nが大きいので、あなたはすぐに電力使用を最適化することができます

最終的な答えであり、後に自身のn倍を乗じた、すべての可能な接尾辞の状態と最初の列

#include <cstdioを> 
する#include <CStringの> 
する#include <キュー> 
の#include <入出力ストリーム> 
の#define ENDL '\ n' 
の#defineはっ長い長
の#define ULL符号なし長い長
の#define Fiの最初
の#define SE第二
の#define融点make_pair 
#define PII対<整数、整数> 
の#define全て(X)x.begin()、x.end()
の#define IO IOS :: sync_with_stdio(偽); cin.tie(0); cout.tie(0)
#define担当者(II、B)のための(INT II =; II <= Bと、++ II)
(INT II = bについて(B、II)当たりの#define; II> =、 - II)
の#define forn(II、X)(INT II =ヘッドの[X]; II、II = E [II] .next)
名前空間stdを使用。
CONST int型MAXN = 1E4 + 10、MAXM = 2E6 + 10。
const int型INF = 0x3f3f3f3f。
constのLL MOD = 1E5;
// constのダブルPI = ACOS(-1.0); 
int型CASN、N、M。
クラス行列{パブリック:
  int型、B。
  ベクター<ベクトル<LL>> X。
  マトリックス(INT _a = 1、INT _b = 1):
    (_a)、B(_B)、X(ベクトル<LL>(B)){} 
  ボイド要素(INTのN){ 
    A = B = N。 X =マトリックス(N、N).X。
    X [i]は[I] = 1;(; iがN <I ++はiが0 = INT)のために 
  } 
  空隙充填(LL XX = 0){ 
    (I = 0 int型私は++; iが<)のための(INT J = 0; J <B; J ++)用
      X [I] [J] = XX。
  } 
  空隙充填(ベクトル<ベクトル<LL>>&Y){ 
    X = Y; = y.size(); B = Y [0] .size()。
  } 
  行列演算子*(行列&M){ 
    マトリックスANS(MB)。
    用(INT J = 0; J <MB; J ++)(; iが<I ++ iが0 = INT)のための
      ための(INT K = 0、B <K。
        ans.x [I] [J] =(ans.x [I] [J] + MOD + MOD(X [i]が[K] * MX [K] [J]%))%MOD。
    ANSを返します。
  } 
  行列演算子+(行列&M){
    マトリックスANS(MB)。
    用(INT J = 0; J <B; J ++)のために(I ++; iは<I = 0 INT)を
        ans.x [I] [J] =(X [I] [J] + MX [I]を[ J] + MOD)%のMOD。
    ANSを返します。
  } 
  行列演算子- (行列&M){ 
    マトリックスANS(MB)。
    用(INT J = 0; J <B; J ++)のために(I ++; iは<I = 0 INT)を
      ans.x [I] [J] =(X [I] [J] -mx [I]を[ J] + MOD)%のMOD。
    ANSを返します。
  } 
  マトリックスPOW(LLのP){ 
    マトリックスANS、T; ans.element(A); t.fill(X)。
    一方、(P){IF(P&1)ANS = T * ANS; Tは= Tの* tの、P >> = 1;} 
    戻りANS。
  } 
}。
CONST INT CSIZE = 4、ミンク= 0。
クラスAUTOM {パブリック:
#define NDノード[今] 
        IF(nd.son [I]){ 
  構造体acnode {INTフラグ、息子[CSIZE]、失敗;}ノード[MAXN]。
  int型のCNT;
  キュー<整数> QUE。
  無効クリア(){ 
    memsetの(ノード、0、はsizeofノード)。
    CNT = 0; 
  } 
  ボイドインサート(CHAR *は、INT LEN = 0){ 
    LEN = STRLEN(S)IF(LEN!)。
    = 0になりましたint型。
    担当者(I、0、lenの-1){ 
      int型、CH = S [i]の-minc。
      (!nd.son [CH])であればnd.son [CH] = ++ CNT; 
      今= nd.son [CH]。
    } 
    nd.flag = 1。
  } 
  )(INITを無効{ 
    = 0今int型。
    担当者(I、0、CSIZE-1)であれば(nd.son [i])とque.push(nd.son [I])。
    (!que.empty()){ながら
      今= que.front(); que.pop()。
      担当者(I、0、CSIZE-1){
          que.push(nd.son [I])。
          ノード[nd.sonは[I] =失敗ノード[nd.fail] [I] .son。
        }他nd.son [I] =ノード[nd.fail] [I] .son。
        ノード[nd.son [I]フラグ| =ノード[ノード[nd.fail] [I] .son]フラグ。
      } 
    } 
  } 
} ACAM。
チャーP [1010]。
INT {main()のIO。
  LL N、M。
  一方、(CIN >> M >> N){ 
    acam.clear()。
    担当者(I、1、M){ 
      CIN >> P。
      INTのL =のSTRLEN(P)。
      担当者(j、0、L-1){ 
        IF(P [j] == 'A')p [j] = 0; 
        他(P [j] == 'C')p [j]が1をIF =。
        他(P [j] == 'G')p [j]が2をIF =。
        他のp [J] = 3; 
      } 
      acam.insert(P、L)。
    } 
    acam.init()。
    int型のMT = ACAM。
    ベクター<ベクトル<LL>> _f(MT + 1、ベクトル<LL>(MT + 1))。
      IF(acam.node [I] .flag)続けます。
      担当者(J、0,3)であれば(!。acam.node [acam.node [i]は.son [J]]フラグ)
        _f [i]の[acam.node [i]は.son [J]] ++; 
    } 
    行列F; f.fill(_f)。
    F = f.pow(N)。
    LL ANS = 0。
    担当者(I、0、MT)ANS =(ANS + FX [0] [i])と%MOD。
    coutの<< ANS <<てendl; 
  } 
  0を返します。
}

 

おすすめ

転載: www.cnblogs.com/nervendnig/p/11233047.html