DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9460 | Accepted: 3545 |
Description
Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.
Input
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Output
Sample Input
4 3 AT AC AG AA
Sample Output
36
题解:
先构建一颗trie树以及它的fail指针
然后给trie树的节点编号,代表这个状态的编号
然后构建一个邻接矩阵Map[i][j]代表从状态i变成状态j有多少种方法
初始化全为0
然后对树做一次dfs
假如 node->next[*]存在且不构成病毒片段(不是单词末尾) map[i][j]++ (i是node的状态编号,j是node->next[*]的状态编号)
如果node->next[*]不存在,就找node->fail->next[*]是否存在,存在就参考上一步,不存在就继续,直至root节点还没找到的话就是 map[i][0]++
现在我们就得到了一个表示状态转换的矩阵
题目的答案就是这个矩阵的N次幂
然后取从root可到的状态的方法总数即可
可参考http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #define MOD 100000
- #define size 200
- using namespace std;
- const int kind = 4;
- struct node
- {
- node *fail; //失败指针
- node * next[kind]; //Tire每个节点的26个子节点(最多26个字母)
- int count; //是否为该单词的最后一个节点
- int state;
- node()
- { //构造函数初始化
- fail = NULL;
- count = 0;
- memset(next, NULL, sizeof (next));
- }
- } *q[500001]; //队列,方便用于bfs构造失败指针
- char keyword[51]; //输入的单词
- char str[1000001]; //模式串
- int head, tail; //队列的头尾指针
- int total;
- long long map[200][200];
- void insert(char *str, node *root)
- {
- node *p = root;
- int i = 0, index;
- while (str[i])
- {
- if (str[i] == 'A') index = 0;
- if (str[i] == 'C') index = 1;
- if (str[i] == 'T') index = 2;
- if (str[i] == 'G') index = 3;
- if (p->next[index] == NULL)
- {
- p->next[index] = new node();
- p->next[index]->state = total++;
- }
- p = p->next[index];
- i++;
- }
- p->count++;
- }
- void build_ac_automation(node *root)
- {
- int i;
- root->fail = NULL;
- q[head++] = root;
- while (head != tail)
- {
- node *temp = q[tail++];
- node *p = NULL;
- for (i = 0; i < kind; i++)
- {
- if (temp->next[i] != NULL)
- {
- if (temp == root)
- temp->next[i]->fail = root;
- else
- {
- p = temp->fail;
- while (p != NULL)
- {
- if (p->next[i] != NULL)
- {
- temp->next[i]->fail = p->next[i];
- if (p->next[i]->count != 0)
- temp->next[i]->count = p->next[i]->count;
- break;
- }
- p = p->fail;
- }
- if (p == NULL)
- temp->next[i]->fail = root;
- }
- q[head++] = temp->next[i];
- }
- }
- }
- }
- void build_matrix(node* now)
- {
- if (now->count > 0) return ;
- for (int i = 0 ; i < kind ; i++)
- {
- if (now->next[i] != NULL)
- {
- if (now->next[i]->count == 0)
- map[now->state][now->next[i]->state]++;
- }
- else
- {
- bool flag = false;
- node* temp = now;
- int temp_s = now->state;
- while (temp->next[i] == NULL && temp->fail != NULL)
- {
- temp = temp->fail;
- if (temp->next[i] != NULL)
- {
- if (temp->next[i]->count == 0)
- map[temp_s][temp->next[i]->state]++;
- flag = true;
- }
- if (temp->state == 0) break;
- }
- if (!flag) map[temp_s][0]++;
- }
- }
- for (int i = 0 ; i < kind ; i++)
- if (now->next[i] != NULL) build_matrix(now->next[i]);
- }
- void MatrixMul(long long ans[size][size],long long cal[size][size])
- {
- long long temp[size][size];
- for (int i = 0 ; i < total ; i++)
- for (int j = 0 ; j < total ; j++)
- temp[i][j] = 0;
- for (int i = 0 ; i < total ; i++)
- for (int j = 0 ; j < total ; j++)
- for (int k = 0 ; k < total ; k++)
- {
- temp[i][j] += ans[i][k] * cal[k][j];
- if (temp[i][j] >= MOD)
- temp[i][j] %= MOD;
- }
- for (int i = 0 ; i < total ; i++)
- for (int j = 0 ; j < total ; j++)
- ans[i][j] = temp[i][j];
- }
- void MatrixPow(long long ans[size][size],long long cal[size][size],int n)
- {
- while (n > 0)
- {
- if (n&1) MatrixMul(ans,cal);
- MatrixMul(cal,cal);
- n >>= 1;
- }
- }
- int main()
- {
- int m,n;
- scanf("%d%d",&m,&n);
- total = 1;
- node *root = new node();
- root->state = 0;
- while (m--)
- {
- char s[20];
- scanf("%s",s);
- insert(s,root);
- }
- build_ac_automation(root);
- for (int i = 0 ; i < total ; i++)
- for (int j = 0 ; j < total ; j++)
- map[i][j] = 0;
- build_matrix(root);
- long long ans[200][200];
- for (int i = 0 ; i < total ; i++)
- for (int j = 0 ; j < total ; j++)
- ans[i][j] = 0;
- for (int i = 0 ; i < total ; i++)
- ans[i][i] = 1;
- MatrixPow(ans,map,n);
- long long out = 0;
- for (int i = 0 ; i < total ; i++)
- out = (out + ans[0][i]) % MOD;
- cout<<out<<endl;
- return 0;
- }