您的位置:首页 > 产品设计 > UI/UE

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

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

建一个字典树,在上面加Fail指针

然后goi,cgo_{i,c} 表示 从i点走字母cc 会到字典树上的哪个点

最后建立邻接矩阵A,ai,ja_{i,j}表示从字典树上的节点i→ji \to j 的可行路径

预处理出字典树上的哪些节点会匹配字符串,删掉它们所在行、列

答案就是 AmA^m 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: