poj 2778
来源:互联网 发布:gulp 压缩js css 编辑:程序博客网 时间:2024/05/18 03:51
这道题类似于poj 1625,只不过字符集变得更小,只有’A’,’G’,’C’,’T’四个字符。相应的,序列的长度大幅度的增加至2*10^9。假设序列长度为m,总的trie图节点数为sz,原先的dp方法的复杂度为O(m*sz^2)。若仍采用dp的方法,那么总的操作数达到10^11,肯定不可取。因此需要其他的方法。矩阵可以解决这个问题。求出trie图的邻接矩阵,两点之间的权值为这两点间的边数,矩阵中的a[i][j]表示由节点i,到节点j走一步的方法数。此矩阵的n次幂后a’[i][j]即为由节点i走n步到节点j的方法数。因此题目的答案a[root][i]的和,(0<=i<sz)。
同样,要记得去除所有危险节点的行和列,即权值标为0,表示没有这条边。
矩阵的计算过程采用快速幂。复杂度为O(log(n))
更多的解释可以参见poj 1625
下面贴代码:
#include <cstdio>#include <queue>#include <cstring>#define sigma_size 4#define maxnode 105#define modnum 100000using namespace std;int m, n;int ch[maxnode][sigma_size];int val[maxnode];int sz;int f[maxnode];int last[maxnode];void initial(){ sz = 1; memset(ch[0], 0, sizeof(ch[0]));}int charget(char a){ switch(a) { case 'A': return 0; case 'G': return 1; case 'C': return 2; case 'T': return 3; } return -1;}void insert(char *S){ int l = strlen(S); int u = 0; for(int i = 0; i < l; i++) { int c = charget(S[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = 1;}void getfail(){ queue<int>q; f[0] = 0; for(int c = 0; c < sigma_size; c++) { int u = ch[0][c]; if(u) { f[u] = 0; q.push(u); last[u] = 0; } } while(!q.empty()) { int r = q.front(); q.pop(); for(int c = 0; c < sigma_size; c++) { int u = ch[r][c]; if(!u) { ch[r][c] = ch[f[r]][c]; continue; } q.push(u); int v = f[r]; while(v && !ch[v][c]) v = f[v]; f[u] = ch[v][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } }}long long matrix[maxnode][maxnode];long long res1[maxnode][maxnode];long long res2[maxnode][maxnode];void buildmatrix(){ memset(matrix, 0, sizeof(matrix)); for(int i = 0; i < sz; i++) { if(val[i] || last[i]) //去除非法节点出边 continue; for(int j = 0 ; j < sigma_size; j++) { if(val[ch[i][j]] || last[ch[i][j]]) continue;//去除非法节点入边 matrix[i][ch[i][j]]++; } }}void mul(long long a[][maxnode], long long b[][maxnode], long long c[][maxnode]){ memset(c, 0, sizeof(matrix)); for(int i = 0; i < sz; i++) for(int j = 0; j < sz; j++) { for(int k = 0; k < sz; k++) c[i][j] += (a[i][k]*b[k][j]); c[i][j] %= modnum; }}void swap(long long a[][maxnode],long long b[][maxnode]){ long long tmp; for(int i = 0; i <sz;i++) for(int j = 0; j<sz;j++) { tmp = a[i][j]; a[i][j] = b[i][j]; b[i][j] = tmp; }}void multiple(int n){ if(n == 1) { for(int i = 0; i < sz; i++) for(int j = 0; j < sz; j++) res1[i][j] = matrix[i][j]; return; } multiple(n / 2); mul(res1, res1, res2); if(n % 2) { mul(res2, matrix, res1); } else swap(res2, res1);}char ban[12];int main(){ initial(); scanf("%d%d", &m, &n); for(int i = 0; i < m; i++) { scanf("%s", ban); insert(ban); } getfail(); buildmatrix(); multiple(n); long long ans = 0; for(int i = 0; i < sz; i++) ans += res1[0][i]; printf("%lld\n",ans%modnum); return 0;}
0 0
- poj 2778
- poj 2778
- poj 2778
- poj 2778
- POJ 2778
- POJ PKU 2778
- poj 2778 DNA Sequence
- POJ 2778 DNA Sequence
- POJ 2778 AC自动机
- poj 2778 DNA Sequence
- Poj 2778 DNA Sequence
- POJ 2778 DNA Sequence
- POJ 2778 DNA Sequence
- POJ 2778 DNA Sequence
- AC自动机-poj 2778
- poj-2778 DNA Sequence
- POJ 2778DNA Sequence
- poj 2778 DNA Sequence
- ppp = 2.4.4 is needed by pptpd-1.3.4-2.rhel5.x86_64的解决办法及原因
- 黑马程序员---基础加强:类加载器
- 简单词法分析程序
- [转]用pyenv 和 virtualenv 搭建单机多版本python 虚拟开发环境
- 完全平方数的个数
- poj 2778
- Sublime Text 3 解决中文乱码问题
- LA 3635 - Pie 【二分】
- 黑马程序员---交通灯管理系统
- C语言实现AES(标准方法)
- 国际版QQ登陆协议的详细分析-工具准备
- windows_socket_易忘函数
- 程序进度条的实现
- SVM算法的理解