1. 程式人生 > >POJ-2778 DNA Sequence

POJ-2778 DNA Sequence

思路:同樣是 AC自動機+矩陣快速冪。。

Code :

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long LL;

const int MAX_M=15;
const int max_tot = 105; 	//最大編號 
const int max_size = 4;	//組成元素個數##
const int mod = 1e5;
char s[15];
int chr[30];
struct mac {
	LL a[max_tot][max_tot];
	int len;
	mac() {
		len = 0;
		memset(a, 0, sizeof(a));
	}
	mac operator*(const mac &c)const {
		mac t;
		t.len = len;
		for (int i = 0; i < len; ++i)
			for (int j = 0; j < len; ++j) {
				t.a[i][j] = 0;
				for (int k = 0; k < len; ++k)
					t.a[i][j] += a[i][k] * c.a[k][j];
				t.a[i][j] %= mod;
			}
		return t;
	}
};

struct AC {
	int trie[max_tot][max_size];
	int val[max_tot];
	int fail[max_tot];
	int size;
	
	void Clear()
	{
		memset(trie, 0, sizeof(trie));
		memset(val, 0, sizeof(val));
		memset(fail,0,sizeof(fail));
		size = 1;
	}
	
	void insert(char *str)
	{
		int k = 0;
		for (int i = 0; str[i]; ++i) 
		{
			int x = chr[str[i]-'A'];
			if (!trie[k][x]){
				trie[k][x] = size++;
			}
			k = trie[k][x];
		}
		val[k] = 1;
	}

	void GetFail()
	{
		queue<int> Q;
		for (int i = 0; i < max_size; ++i)
			if(trie[0][i])	Q.push(trie[0][i]);
		while (!Q.empty()) {
			int r=Q.front(),k;	Q.pop();
			if(val[fail[r]])	val[r]=1;
			for (int i = 0; i < max_size; ++i) 
			{
				k = trie[r][i];
				if (k) {
					Q.push(k);
					fail[k] = trie[fail[r]][i];
				}else	trie[r][i] = trie[fail[r]][i];
			}
		}
	}
}ac;

mac Pow(mac a, LL b){
	mac ans;
	ans.len = a.len;
	for (int i = 0; i < a.len; ++i)
		ans.a[i][i] = 1;
	while (b) {
		if (b & 1)	ans = ans*a;
		a = a * a;
		b >>= 1;
	}
	return ans;
}

int main()
{
	chr['A'-'A']=0;	chr['C'-'A']=1;	chr['T'-'A']=2;	chr['G'-'A']=3;
	LL m,n;
    while(~scanf("%lld%lld",&m,&n)){
		ac.Clear();
		for (int i = 0; i < m; ++i)
		{
			scanf("%s",s);
			ac.insert(s);
		}
		ac.GetFail();
		mac ans=mac();
		ans.len = ac.size;
		for (int i = 0; i < ac.size; ++i) 
			for (int j = 0; j < max_size; ++j)
			{
				int u = ac.trie[i][j];
				if (!ac.val[u])	++ans.a[i][u];
			}
		ans = Pow(ans, n);
		LL sum = 0;
		for (int i = 0; i < max_tot; ++i)
			sum = (sum + ans.a[0][i]) % mod;
		printf("%lld\n",sum);
	}
	
	return 0;
}

相關推薦

POJ 2778 DNA Sequence(AC自動機+矩陣快速冪)

ace str etc cto .org empty pan dac http http://poj.org/problem?id=2778 題意:給出一些病毒字符串,只由A,T,C,G組成,現在要用著4個字符組成長度為n的字符串,且字符串中不可以包含任一病毒字符串,問共

POJ 2778 DNA Sequence (AC自動機+DP+矩陣)

ont val put 題意 mat stdin +++ iostream bit 題意:給定一些串,然後讓你構造出一個長度為 m 的串,並且不包含以上串,問你有多少個。 析:很明顯,如果 m 小的話 ,直接可以用DP來解決,但是 m 太大了,我們可以認為是在AC自動機圖中

poj 2778 DNA Sequence AC自動機+矩陣快速冪

DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19923  

【AC自動機+矩陣快速冪】POJ - 2778 - DNA Sequence & HDU - 2243 - 考研路茫茫——單詞情結

POJ - 2778 - DNA Sequence 題目連結<http://poj.org/problem?id=2778> 題意: DNA序列只包含ACTG四個字元,已知一些病毒的DNA序列,問你序列長度為n(1 <= n <=2000000000)且不

POJ-2778 DNA Sequence

思路:同樣是 AC自動機+矩陣快速冪。。 Code : #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #inclu

POJ 2778 DNA Sequence【AC自動機+矩陣快速冪】

題意:給m個病毒字串,問長度為n的DNA片段有多少種沒有包含病毒串的。 首先解決這個問題:給定一個有向圖,問從A點恰好走k步(允許重複經過邊)到達B點的方案數mod p的值     把給定的圖轉為鄰接矩陣,即A(i,j)=1當且僅當存在一條邊i->j。令C=A*A,

POJ 2778 DNA Sequence (AC自動機 + 矩陣快速冪)

解析:AC自動機 + 矩陣加速(快速冪)。 這個時候AC自動機 的一種狀態轉移圖的思路就很透徹了,AC自動機就是可以確定狀態的轉移。 AC程式碼: #include <iostream> #include <cstdio> #include

【AC自動機+矩陣快速冪】 POJ 2778 DNA Sequence

先構建AC自動機,然後通過AC自動機構建矩陣,最後矩陣快速冪即可。。。 #include <iostream> #include <queue> #include <stack> #include <map>

DNA Sequence POJ - 2778 AC 自動機 矩陣乘法

定義過載運算的時候一定要將矩陣初始化,因為這個調了一上午...... Code: #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<st

DNA Sequence POJ - 2778 AC自動機 矩陣快速冪

題解 給m個長度10以內的病毒串 問長度為n的主串且不匹配任意一個病毒串的有多少個 m最大10所以節點數不超過100 利用AC自動機建圖 建立鄰接矩陣表示從節點i到節點j能轉移的字元數量 除去字元結束節點和fail指標路徑上是結束節點 通過N個鄰接矩陣相乘即可得到i到j走N步的方案數

POJ 2778DNA Sequence(AC自動機+矩陣快速冪)

DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6232 Accepted: 2213 Description It's well known that DNA

DNA Sequence POJ

這個題目利用了圖的思想,如果我們把ac自動機上面所有的點挑出來,建立一個矩陣M,表示i到j有幾條路徑可走,根據鄰接矩陣的性質,M的n次冪就表示從i到j走n步可以有多少條路。 如果我們結合ac自動機來看,那M的n第一行就表示長為n的,可行的字串數有多少了,就對應答案了

HDU 1560 DNA sequenceDNA序列)

memory nes rgb each 12px align div printf c++ p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibr

POJ 1141 Brackets Sequence (區間DP)

ive bsp rip mes character har typedef som memset Description Let us define a regular brackets sequence in the following way: 1.

poj 1019 Number Sequence (數學)

http scan oid urn problem can set clu return 鏈接:http://poj.org/problem?id=1019 分析:就是計數的問題。。可以先算出112123...m共有多少位,具體式子看代碼。。然後二分取一個最大的小於n的m,

[poj2778]DNA Sequence(AC自動機+矩陣快速冪)

build printf class queue cstring node mod names sequence 解題關鍵:卡時限過的,正在找原因中。 1 #include<cstdio> 2 #include<cstring>

POJ 3691 DNA repair ( Trie圖 && DP )

queue src can bsp next mem %d mil ++ 題意 : 給出 n 個病毒串,最後再給出一個主串,問你最少改變主串中的多少個單詞才能使得主串中不包含任何一個病毒串 分析 : 做多了AC自動機的題,就會發現這些題有些都是很套路的題目。在構建 Tr

Leetcode: Repeated DNA Sequence

and == 10個 nas rect 想是 運算 tco contains 方法2:進一步的方法是用HashSet, 每次取長度為10的字符串,O(N)時間遍歷數組,重復就加入result,但這樣需要O(N)的space, 準確說來O(N*10bytes), java而言

DNA sequence open reading frames (ORFs) | DNA序列的開放閱讀框ORF預測

ear xtend sta plus htm allow dev program HR 常見的ORF預測工具 Open Reading Frame Finder - NCBI ORF Finder - SMS OrfPredictor - YSU 基本概念 開放

POJ 1141 Brackets Sequence

lar == and style 一個 clas space file 空串 Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular seq