POJ 2778 DNA Sequence
2016-05-19 20:19
555 查看
给m个长度不超过10的模式串,求长度为n小于200000000的不包含任意一个模式串的种数。
最开始最这道题的时候毫无头绪,最后看了这篇文章才理解了:(http://www.cnblogs.com/Booble/archive/2010/12/09/1901626.html),但是首先还要知道矩阵的一些应用:(http://www.matrix67.com/blog/archives/276)
首先建立好模式串,然后用建好的end数组和next数组跑出对应的状态转移数组,枚举结点,当当前结点的end和后继状态即next数组的end被标记时代表了经过了病毒串不可取,否则令状态转移数组自增代表可以从当前结点走到后继结点。实际上我们可以根据dp
[s],n为字符串长度,s为状态来进行状态转移方程最后的dp
[i]的总和就是答案。i是每一个结点。但由于这道题的n过大,dp一定超时。又因为本题可以看成从起点0走到结点j经过了n步且中途不经过模式串的路径之和。这就可以用矩阵来求了,是因为矩阵相乘时的方式具体可以看matrix67的文章,而且矩阵这种特性也完成了之前说的dp状态转移的,非常的奇妙。用矩阵快速幂可以很好的解决时间上的问题。
代码如下
最开始最这道题的时候毫无头绪,最后看了这篇文章才理解了:(http://www.cnblogs.com/Booble/archive/2010/12/09/1901626.html),但是首先还要知道矩阵的一些应用:(http://www.matrix67.com/blog/archives/276)
首先建立好模式串,然后用建好的end数组和next数组跑出对应的状态转移数组,枚举结点,当当前结点的end和后继状态即next数组的end被标记时代表了经过了病毒串不可取,否则令状态转移数组自增代表可以从当前结点走到后继结点。实际上我们可以根据dp
[s],n为字符串长度,s为状态来进行状态转移方程最后的dp
[i]的总和就是答案。i是每一个结点。但由于这道题的n过大,dp一定超时。又因为本题可以看成从起点0走到结点j经过了n步且中途不经过模式串的路径之和。这就可以用矩阵来求了,是因为矩阵相乘时的方式具体可以看matrix67的文章,而且矩阵这种特性也完成了之前说的dp状态转移的,非常的奇妙。用矩阵快速幂可以很好的解决时间上的问题。
代码如下
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<algorithm> #include<queue> using namespace std; const int MOD=100000; struct Matrix { long long mat[210][210]; int n; Matrix(){} Matrix(int _n) { n=_n; for(int i=0;i<n;i++) for(int j=0;j<n;j++) mat[i][j] = 0; } Matrix operator *(const Matrix &b)const { Matrix ret = Matrix(n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) ret.mat[i][j]+=mat[i][k]*b.mat[k][j]%MOD; return ret; } }; Matrix pow_M(Matrix a,int n) { Matrix ret = Matrix(a.n); for(int i=0;i<a.n;i++) ret.mat[i][i] = 1; Matrix tmp = a; while(n) { if(n&1)ret=ret*tmp; tmp=tmp*tmp; n>>=1; } return ret; } struct Tree { int next[210][26],fail[210],end[210]; int root,L; int newnode() { for(int i=0;i<128;i++) next[L][i]=-1; end[L++]=0; return L-1; } void init() { L=0; root=newnode(); } int judge(char c) { if(c=='A') return 0; else if(c=='T') return 1; else if(c=='C') return 2; return 3; } void insert(char *s) { int len=strlen(s); int p=root; for(int i=0;i<len;i++) { int id=judge(s[i]); if(next[p][id]==-1) next[p][id]=newnode(); p=next[p][id]; } end[p]++; } void build() { queue<int>q; int p=root; fail[root]=root; for(int i=0;i<4;i++) { if(next[p][i]==-1) next[p][i]=root; else { fail[next[p][i]]=root; q.push(next[p][i]); } } while(!q.empty()) { p=q.front(); q.pop(); if(end[fail[p]]) end[p]=1; for(int i=0;i<4;i++) { if(next[p][i]==-1) { next[p][i]=next[fail[p]][i]; } else { fail[next[p][i]]=next[fail[p]][i]; q.push(next[p][i]); } } } } int used[1010]; void query(char *s,int n) { int len=strlen(s); int p=root; bool flag=false; memset(used,0,sizeof(used)); for(int i=0;i<len;i++) { int id=s[i]; p=next[p][id]; int temp=p; while(temp!=root) { if(end[temp]!=-1) { used[end[temp]]++; flag=true; } temp=fail[temp]; } } } Matrix getMatrix() { Matrix ret = Matrix(L); for(int i=0;i<L;i++) for(int j=0;j<4;j++) if(!end[i]&&!end[next[i][j]]) ret.mat[i][next[i][j]]++; return ret; } void debug() { for(int i=0;i<L;i++) { printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]); for(int j=0;j<26;j++) printf("%2d",next[i][j]); printf("]\n"); } } }; Tree ac; char str[20]; int main() { int n,L; while(~scanf("%d %d",&n,&L)) { ac.init(); for(int i=1;i<=n;i++) { scanf("%s",str); ac.insert(str); } ac.build(); Matrix a=ac.getMatrix(); a=pow_M(a,L); long long ans=0; for(int i=0;i<ac.L;i++) { ans+=a.mat[0][i]; } printf("%lld\n",ans%100000); } }
相关文章推荐
- Poj 1904 King's Quest 强连通分量
- gui数据传递的方式讨论汇总
- [UESTC1059]秋实大哥与小朋友(线段树, 离散化)
- 阅读郭林《第一行代码》的笔记——第3章 软件也要拼脸蛋,UI开发的点点滴滴
- 04 - the behavior of the UICollectionViewFlowLayout is not defined
- UITableViewCell设置编辑功能
- UI进阶 即时通讯之XMPP环境搭建
- String,StringBuffer与StringBuilder的区别??
- 63. Unique Paths II
- android开发不可不知的UI知识
- 【Arduino官方教程第一辑】示例程序 4-10 串口事件
- HDU 4667 Building Fence(求凸包的周长)
- 键盘样式(UIKeyboardType)
- Java问题总结33之利用UUID生成全局唯一码(Scala环境运行)
- 【Arduino官方教程第一辑】示例程序 4-9 串口双向调用(使用ASCII字符串)
- 加载图片显示时的图片变形问题(UIImageView)
- 你该知道的 TValue
- Uva1605——Building for UN
- Longest Increasing Subsequence
- OData入门:OData Java和SAP UI5的几个帖子