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所在行的和
建一个字典树,在上面加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; }
相关文章推荐
- Codeforces Round #327 (Div. 2)D. Chip 'n Dale Rescue Rangers
- UEST OJ1222(DFS)
- Codeforces Round #327 (Div. 2)A. Wizards' Duel
- UESTC OJ1221(DFS)
- 免费 UGUI 插件 Inventory Master 背包系统使用方法
- 编程技巧:使用整数同时进行多个true|false判断
- java-buildpack源码分析之Detect
- java-buildpack源码分析之Compile
- java-buildpack源码分析之Release
- UESTC OJ1220(最短路)
- requestLayout() 和 invalidate()的区别
- bzoj3538【Usaco2014 Open】Dueling GPS
- Opencv 鼠标事件GUI
- 黑马程序员——Java基础(十一)之GUI
- Lightoj 1100 - Again Array Queries (枚举剪枝)
- Java中String ,StringBuffer和StringBuilder的区别
- Qt基础——UI文件.h文件说明
- OC 非常用类 --- NSValue
- jd-gui--class文件的反编译工具
- UI作品制作