POJ 2778 DNA Sequence AC自动机+矩阵优化 *
来源:互联网 发布:公钥密码算法 编辑:程序博客网 时间:2024/05/24 22:43
题目地址:http://poj.org/problem?id=2778
数据很大,二维数组开不下,所以第一次写用了滚动数组,但是TLE
代码如下:
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<map>#include<string>#include<vector>using namespace std;typedef long long LL;const int letter=4;const int INF=0x3f3f3f3f;struct Node{Node *pChilds[letter],*pPrev;bool bBadNode;Node(){memset(pChilds,0,sizeof(pChilds));pPrev=NULL; bBadNode=false;}}tree[100+5];char patten[20+5];LL d[2][100+5];int nNode;map<char,int> idx;//d[i][j]要长度为i到达节点j,也即是tree[j] 字符串个数 void Insert(Node* root,char* s){for(int i=0;s[i];i++){if(root->pChilds[idx[s[i]]]==NULL)root->pChilds[idx[s[i]]]=tree+nNode++;root=root->pChilds[idx[s[i]]];}root->bBadNode=true;}void BuildDfa(){for(int i=0;i<letter;i++)tree[0].pChilds[i]=tree+1;tree[1].pPrev=tree;tree[0].pPrev=NULL;queue<Node*> Q;Q.push(tree+1);while(!Q.empty()){Node* root=Q.front(); Q.pop();for(int i=0;i<letter;i++){Node* p=root->pChilds[i];if(p==NULL) continue;Node* pPrev=root->pPrev;while(pPrev!=NULL){if(pPrev->pChilds[i]!=NULL){p->pPrev=pPrev->pChilds[i];if(p->pPrev->bBadNode) p->bBadNode=true;break;}else pPrev=pPrev->pPrev;}Q.push(p);}}}int main(){idx['A']=0;idx['T']=1,idx['G']=2,idx['C']=3;int N,M; cin>>M>>N; nNode=2;for(int i=0;i<M;i++){scanf("%s",patten);Insert(tree+1,patten);}BuildDfa();d[0][1]=1;for(int i=0;i<N;i++){memset(d[i%2^1],0,sizeof(d[0]));for(int j=1;j<nNode;j++){if(tree[j].bBadNode) continue;for(int k=0;k<letter;k++){Node* pPrev=tree+j;while(pPrev){if(pPrev->pChilds[k]!=NULL){if(pPrev->pChilds[k]->bBadNode) break;int son=pPrev->pChilds[k]-tree;d[i%2^1][son]+=d[i%2][j];if(d[i%2^1][son]>100000) d[i%2^1][son]-=100000;break;} pPrev=pPrev->pPrev;} }}}LL ans=0;for(int i=1;i<nNode;i++) {ans+=d[N%2][i];if(ans>100000) ans-=100000;} cout<<ans;return 0;}
下面用矩阵优化
d[i][j]表示i节点到j节点的个数
也即是 d[i][j]=∑ d[i][k]+d[n][k]
这和矩阵的运算法则一样
所以直接矩阵快速幂n次就好了
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<map>#include<string>#include<vector>using namespace std;typedef long long LL;const int letter=4;const int INF=0x3f3f3f3f;struct Matrix{ LL a[100+5][100+5]; int r; // r*r Matrix(int r=100+5):r(r){memset(a,0,sizeof(a));} //初始化长 void MakeI(int x){ //变为x*E的单位矩阵 memset(a,0,sizeof(a)); for(int i=0;i<r;i++) a[i][i]=x; } Matrix operator * (const Matrix& m) { //矩阵乘法 Matrix result(r); for(int i=0;i<r;i++) for(int j=0;j<r;j++) { for(int k=0;k<r;k++) result.a[i][j]+=a[i][k]*m.a[k][j]; } return result; } Matrix operator % (const int p){ //矩阵对每个元素取余 Matrix result(*this); for(int i=0;i<r;i++) for(int j=0;j<r;j++) result.a[i][j]%=p; return result; } Matrix operator + (const Matrix& m){ //矩阵互相相加 Matrix result(r); for(int i=0;i<r;i++) for(int j=0;j<r;j++) result.a[i][j]=a[i][j]+m.a[i][j]; return result; } Matrix operator + (int n){ //加上个常数 Matrix result(r); result.MakeI(n); return *this+result; } }; Matrix PowMod(const Matrix& m,int k,int p) //矩阵快速幂 { //m^k mod p int r=m.r; Matrix result(r); result.MakeI(1); //变成单位矩阵 Matrix base=m; while(k){ if(k&1) result=result*base%p; base=base*base%p; k>>=1; } return result; }struct Node{Node *pChilds[letter],*pPrev;bool bBadNode;Node(){memset(pChilds,0,sizeof(pChilds));pPrev=NULL; bBadNode=false;}}tree[100+5];char patten[20+5];int nNode;map<char,int> idx;//d[i][j] 指节点i到j的步数 i,j都是安全节点,且其中也不经过危险节点 void Insert(Node* root,char* s){for(int i=0;s[i];i++){if(root->pChilds[idx[s[i]]]==NULL)root->pChilds[idx[s[i]]]=tree+nNode++;root=root->pChilds[idx[s[i]]];}root->bBadNode=true;}void BuildDfa(){for(int i=0;i<letter;i++)tree[0].pChilds[i]=tree+1;tree[1].pPrev=tree;tree[0].pPrev=NULL;queue<Node*> Q;Q.push(tree+1);while(!Q.empty()){Node* root=Q.front(); Q.pop();for(int i=0;i<letter;i++){Node* p=root->pChilds[i];if(p==NULL) continue;Node* pPrev=root->pPrev;while(pPrev!=NULL){if(pPrev->pChilds[i]!=NULL){p->pPrev=pPrev->pChilds[i];if(p->pPrev->bBadNode) p->bBadNode=true;break;}else pPrev=pPrev->pPrev;}Q.push(p);}}}int main(){idx['A']=0;idx['T']=1,idx['G']=2,idx['C']=3;int N,M; cin>>M>>N; nNode=2;for(int i=0;i<M;i++){scanf("%s",patten);Insert(tree+1,patten);}BuildDfa();Matrix d(nNode);for(int i=1;i<nNode;i++){if(tree[i].bBadNode) continue;for(int j=0;j<letter;j++){Node* pPrev=tree+i;while(pPrev){if(pPrev->pChilds[j]!=NULL){if(pPrev->pChilds[j]->bBadNode) break;int son=pPrev->pChilds[j]-tree;d.a[i][son]++;if(d.a[i][son]>=100000) d.a[i][son]-=100000;break;} pPrev=pPrev->pPrev;} }} Matrix m=PowMod(d,N,100000);LL ans=0;for(int i=1;i<nNode;i++)if(!tree[i].bBadNode) {ans+=m.a[1][i];if(ans>=100000) ans-=100000;}cout<<ans;return 0;}
0 0
- POJ 2778 DNA Sequence AC自动机DP的矩阵优化
- POJ 2778 DNA Sequence AC自动机+矩阵优化 *
- POJ 2778 DNA Sequence(AC自动机+矩阵)
- 【POJ】2778 DNA Sequence AC自动机+矩阵
- Poj 2778 DNA Sequence (AC自动机+矩阵)
- POJ 2778 DNA Sequence (AC 自动机+矩阵)
- POJ 2778 DNA Sequence && AC自动机 矩阵 矩阵加速
- poj2778--DNA Sequence(AC自动机+矩阵优化)
- poj2778--DNA Sequence(AC自动机+矩阵优化)
- poj 2778 DNA Sequence //AC自动机+矩阵乘法
- POJ 2778:DNA Sequence(AC自动机+矩阵快速幂)
- poj 2778 DNA Sequence 【ac自动机 + dp + 矩阵快速幂】
- POJ 2778 DNA Sequence AC自动机 矩阵加速DP
- POJ 2778 DNA Sequence【AC自动机+矩阵快速幂】
- poj 2778 DNA Sequence(AC自动机+矩阵快速幂)
- POJ 2778 DNA Sequence(AC自动机+矩阵幂DP)
- [AC自动机+dp+矩阵快速幂] poj 2778 DNA Sequence
- POJ 2778 DNA Sequence AC自动机+DP+矩阵二分加速
- 迭代器的使用之双向循环链表
- Linux下Nagios的安装与配置
- linux后台运行和关闭、查看后台任务
- System类
- 理解EJB
- POJ 2778 DNA Sequence AC自动机+矩阵优化 *
- Linux下Samba服务的搭建
- HDU 2795 单点更新 + 区间最值
- Android 6.0 运行时权限处理
- window.open打开子页面,并选择回填的数据到父页面,替换了div弹出层的形式
- CLion: A cross-platform IDE for C and C++
- 乞丐版HTML5播放器
- 219_focusableTouchInMode属性解析
- 220_scaleType属性分析