POJ-2778 DNA Sequence

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/C_13579/article/details/82780080

地址:http://poj.org/problem?id=2778

思路:同样是 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;
}

猜你喜欢

转载自blog.csdn.net/C_13579/article/details/82780080