POJ 2778

一道非常非常优秀的题目,学到了很多

首先是进一步加深对于AC自动机理解,这种将自动机看作图的思路实在是太惊艳了。理解0理解1

此外学习了快速幂的方法,效率显著提升。快速幂

最后,关于高维数组和指针之间的关系,以及typedef具体用法进一步理解,还有指针、函数、数组三种声明的解析

美中不足的是粗心临门一脚打印答案的时候,忘记这时候也要模运算,好在最终很快查出来这个问题

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxs= 105;
const int maxl= 15;
typedef long long MATRIX[maxs][maxs];
typedef long long (*MATRIX_PTR)[maxs];

char str[maxl];
MATRIX pac, aux, res;
MATRIX_PTR pb, pa, pr;
map<char, int> idx;
struct Trie
{
	int L, root;
	int next[maxs][4], fail[maxs], tag[maxs];
	MATRIX b_pac;
	void Init()
	{
		L= 0;
		root= NewNode();
	}
	int NewNode()
	{
		for (int i= 0; i< 4; ++i){
			next[L][i]= -1;
		}
		tag[L++]= 0;
		return L-1;
	}
	void insert(char buf[])
	{
		int lth= strlen(buf);
		int now= root;
		for (int i= 0; i< lth; ++i){
			int id= idx.at(buf[i]);
			if (-1== next[now][id]){
				next[now][id]= NewNode();
			}
			now= next[now][id];
		}
		++tag[now];
	}
	void build()
	{
		queue<int> Q;
		fail[root]= root;
		int now;

		for (int i= 0; i< 4; ++i){
			if (-1== next[root][i]){
				next[root][i]= root;
			}
			else{
				fail[next[root][i]]= root;
				Q.push(next[root][i]);
			}
		}

		while (!Q.empty()){
			now= Q.front();
			Q.pop();
			// attention here
			if (!tag[now] && tag[fail[now]]){
				tag[now]= 1;
			}

			for (int i= 0; i< 4; ++i){
				if (-1== next[now][i]){
					next[now][i]= next[fail[now]][i];
				}
				else{
					fail[next[now][i]]= next[fail[now]][i]; 
					Q.push(next[now][i]);
				}
			}
		}
	}
	int setMatrix(MATRIX pac)
	{
		build();
		for (int i= 0; i< L; ++i){
			for (int j= 0; j< L; ++j){
				b_pac[i][j]= 0;
			}
		}
		for (int i= 0; i< L; ++i){
			if (tag[i]){
				continue;
			}
			for (int j= 0; j< 4; ++j){
				++b_pac[i][next[i][j]];
			}
		}
		int tot= 0;

		for (int i= 0; i< L; ++i){
			if (tag[i]){
				continue;
			}
			int cnt= 0;
			for (int j= 0; j< L; ++j){
				if (!tag[j]){
					pac[tot][cnt++]= b_pac[i][j];
				}
			}
			++tot;
		}
		return tot;
	}
}ac;

void MatMultiple(const MATRIX lhs, const MATRIX rhs, MATRIX res, const int tot)
{
	for (int i= 0; i< tot; ++i){
		for (int j= 0; j< tot; ++j){
			res[i][j]= 0;
			for (int k= 0; k< tot; ++k){
				res[i][j]+= lhs[i][k]*rhs[k][j];
			}
			res[i][j]%= 100000;
		}
	}
}
void FastPower(MATRIX base, MATRIX res, int power, const int tot)
{
	for (int i= 0; i< tot; ++i){
		res[i][i]= 1;
		for (int j= i+1; j< tot; ++j){
			res[i][j]= res[j][i]= 0;
		}
	}

	pb= base;
	pa= aux;
	pr= res;
	while (power > 0){
		if (power & 1){
			 MatMultiple(pr, pb, pa, tot);
			 swap(pa, pr);
		}
		power>>= 1;
		MatMultiple(pb, pb, pa, tot);
		swap(pa, pb);
	}
}
int main(int argc, char const *argv[])
{
	int m, n;
	idx.insert(make_pair('A', 0));
	idx.insert(make_pair('T', 1));
	idx.insert(make_pair('C', 2));
	idx.insert(make_pair('G', 3));

	scanf("%d %d", &m, &n);
	ac.Init();
	for (int i= 0; i< m; ++i){
		scanf(" %s", str);
		ac.insert(str);
	}
	int tot= ac.setMatrix(pac);
	FastPower(pac, res, n, tot);
	long long ans= 0;
	for (int i= 0; i< tot; ++i){
		ans+= pr[0][i];
	}
	printf("%lld", ans%100000);

	return 0;
}
posted @ 2021-04-28 13:30  IdiotNe  阅读(39)  评论(0编辑  收藏  举报