POJ 2778 AC自动机+dp+矩阵快速幂

给出至多10个字符串。。长度不超过10。。且字符串均由ATCG四个字母组成。

构造一个长度为L的串。使给出的字符串均不是它的字串。求方案数。

对给出的字符串构造AC自动机。然后在AC自动机上进行DP。。

对于ac自动机,每输入一个字符。其对应自动机上的结点也发生移动。

f[i][j]表示第i个字符之后位于自动机上第j个结点。

f[i][j]=k0*f[i-1][0]+k1*f[i-1][1]+k2*f[i-1][2]+......

由于L太大。构造矩阵后用矩阵快速幂求解。

 

(具体看这里 http://blog.henix.info/blog/poj-2778-aho-corasick-dp.html

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define rep(i,a,b) for(int i=a;i<b;++i)
using namespace std;
 
const int MAXN = 100;
const int MAXC = 4;
const int MOD = 100000;
int N;
typedef long long ll;
 
struct Matrix{
    int data[MAXN][MAXN];
    Matrix(){
        memset(data,0,sizeof(data));
    }
    Matrix operator * (Matrix &b) {
        Matrix r;
        rep(i,0,N)
            rep(j,0,N)
                rep(k,0,N){
                    r.data[i][j]+=(1ll*data[i][k]*b.data[k][j])%MOD;
                    r.data[i][j]%=MOD;
                }
        return r;
    }
};
 
struct Tnode{
    Tnode *ch[MAXC];
    Tnode *f;
    bool flag;
} *init;
 
Tnode pool[MAXN];
int cnt;
 
inline int lx(char c){
    if (c=='A') return 0;
    if (c=='T') return 1;
    if (c=='C') return 2;
    if (c=='G') return 3;
}
 
void insert(char *s){
    Tnode *now = init;
    while(*s){
        int p = lx(*s++);
        if (!now->ch[p]) now->ch[p]=&pool[++cnt];
        now = now->ch[p];
    }
    now->flag=true;
}
 
void build(){
    queue <Tnode*> q;
    q.push(init);
    while(!q.empty()){
        Tnode *now = q.front();
        q.pop();
        rep(i,0,MAXC){
            if (now->ch[i]){
                Tnode *p=now->f;
                while(p && !p->ch[i]) p=p->f;
                now->ch[i]->f = p?p->ch[i]:init;
                q.push(now->ch[i]);
            }
        }
    }
 
    init->f=init;
    rep(i,0,MAXC)
        if (init->ch[i]) q.push(init->ch[i]);
            else init->ch[i]=init;
    while(!q.empty()){
        Tnode *now = q.front();
        if (now->f->flag) now->flag=true;
        q.pop();
        rep(i,0,MAXC)
            if (now->ch[i]) q.push(now->ch[i]);
                else now->ch[i]=now->f->ch[i];
    }
}
 
void show(int p){
    cout << "Fail: " << pool[p].f-pool << endl;
    rep(i,0,MAXC) cout << pool[p].ch[i]-pool << " ";
    cout << endl;
}
 
Matrix callMatrix(){
    N = cnt+1;
    Matrix R;
    rep(i,0,N){
        if (pool[i].flag) continue;
        rep(p,0,MAXC)
            R.data[pool[i].ch[p]-pool][i]++;
    }
    return R;
}
 
Matrix pow(Matrix x,ll e){
    Matrix r;
    rep(i,0,N) r.data[i][i]=1;
    for (;e;e>>=1,x=x*x)
        if (e&1) r=r*x;
    return r;
}
 
char s[20];
Matrix X;
int main(){
    freopen("in.txt","r",stdin);
    init = &pool[0];
    memset(pool,0,sizeof(pool));
    cnt=0;
    int M,L;
    scanf("%d%d\n",&M,&L);
    while(M--){
        scanf("%s",s);
        insert(s);
    }
    build();
    X = callMatrix();
    X = pow(X,L);
    int ans=0;
    rep(i,0,N){
        if (pool[i].flag) continue;
        ans+=X.data[i][0];
        ans%=MOD;
    }
    cout << ans << endl;
}
View Code

 

 

posted @ 2013-09-24 13:06  qinhang3  阅读(138)  评论(0编辑  收藏  举报