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;
}