POJ 2778(DNA Sequence-Fail指针+矩阵快速幂)

来源:互联网 发布:未注册双拼域名 编辑:程序博客网 时间:2024/06/11 13:10

在只有4个字母的字符集中,给你n个字符串(n*L<=100) ,求长度为m的且不包含前面任何一个序列的字符串个数(m<=2000000000)

建一个字典树,在上面加Fail指针
然后goi,c 表示 从i点走字母c 会到字典树上的哪个点
最后建立邻接矩阵A,ai,j表示从字典树上的节点ij 的可行路径
预处理出字典树上的哪些节点会匹配字符串,删掉它们所在行、列
答案就是 Am root所在行的和

#include<cstdio>#include<iostream>#include<functional>#include<vector>#include<cstring>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--))  #define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000)#define MAXN (100+10)#define MAXNode (100+10)#define Sigma_size (5)#define pb push_back long long mul(long long a,long long b){return (a*b)%F;}long long add(long long a,long long b){return (a+b)%F;}long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}typedef long long ll;void upd(ll &a,ll b){a=(a%F+b%F)%F;}ll pow2(ll a,ll b){    if (b==1) return a;    if (b==0) return 1;    ll p=pow2(a,b/2)%F;    p=p*p%F;    if (b&1) p=p*a%F;    return p;}struct M  {      int n,m;      ll a[MAXN][MAXN];      M(int _n=0){n=m=_n;MEM(a);}     M(int _n,int _m){n=_n,m=_m;MEM(a);}    void mem (int _n=0){n=m=_n;MEM(a);}    void mem (int _n,int _m){n=_n,m=_m;MEM(a);}    friend M operator*(M a,M b)      {          M c(a.n,b.m);          For(k,a.m)            For(i,a.n)                  For(j,b.m)                      c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%F;          return c;         }      void make_I(int _n)      {          n=m=_n; MEM(a)        For(i,n) a[i][i]=1;      }  }A;int n;ll m;class Trie{public:    int ch[MAXNode][Sigma_size],fa[MAXNode];    int fail[MAXNode],go[MAXNode][Sigma_size];    int siz;    bool tag[MAXNode];    void mem(){siz=0; MEM(tag) MEM(ch) MEM(fa) MEM(go) MEM(fail) }    int idx(char c){return c=='A' ? 0 :c=='T' ? 1 :c=='C' ? 2 :3 ;}    void insert(char *s)    {        int u=0,n=strlen(s);        Rep(i,n)        {            int c=idx(s[i]);            if (!ch[u][c])            {                ++siz;                MEM(ch[siz]);                ch[u][c]=siz;                fa[siz]=u;            }            u=ch[u][c];        }        tag[u]=1;    }    int q[MAXNode+10];    void make_fail()    {        int Head=1,Tail=1;        q[Head]=0;        For(i,siz) fail[i]=0;        while(Head<=Tail) {            int u=q[Head];            Rep(c,4)            {                if (ch[u][c]) {                    q[++Tail]=ch[u][c];                    if (u==0) fail[ch[u][c]]=0;                    else fail[ch[u][c]]=go[ fail[u] ][c];                    go[u][c]=ch[u][c];                }                else {                    go[u][c]=go[fail[u]][c];                }            }             Head++;         }//      For(i,siz) cout<<fail[i]<<" ";cout<<endl;        For(i,Tail) {            int now=q[i];            if (tag[fail[now]]) tag[now]=1;        }        int t=0;        vector<int> Q;        int h[MAXN]={0};        Rep(i,siz+1) {            if (!tag[i]) Q.pb(i),h[i]=++t;        }        A.mem(t);        For(i,t)        {            int now=Q[i-1];             Rep(j,4) {                int v=go[now][j];                if (h[v]) A.a[i][h[v]]++;             }         } //      For(i,t) {//          For(j,t) cout<<A.a[i][j]<<' ';//          cout<<endl;//      }    }}T;M pow2(M a,ll b)  {      M c;c.make_I(a.n);        static bool a2[1000000];        int n=0;while (b) a2[++n]=b&1,b>>=1;        For(i,n)        {            if (a2[i]) c=c*a;            a=a*a;        }        return c;    }char s[20];int main(){//  freopen("poj2778.in","r",stdin);//  freopen(".out","w",stdout);    cin>>n>>m;    T.mem();    For(i,n) {        scanf("%s",s);        T.insert(s);    }    T.make_fail();    A=pow2(A,m);    ll ans=0;    For(i,A.n) upd(ans,A.a[1][i]);    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击