BZOJ1009:看了下面那道反过来看这一道还真是有点豁然开朗的感觉。
POJ2778:这题是它的加强版,模式串变成了M个,那么用AC自动机就行了,不过看似简单但是理解AC自动机是一个图的过程还是有些奇妙的。
代码如下:
BZOJ1009:
#include "cstdio"
#include "cstdlib"
#include "iostream"
#include "algorithm"
#include "cstring"
#include "queue"
using namespace std;
#define MAX_SIZE 50
#define INF 0x3F3F3F3F
#define Eps
#define Mod K
inline int Get_Int()
{
int Num = 0, Flag = 1;
char ch;
do
{
ch = getchar();
if(ch == '-')
Flag *= -1;
}
while(ch < '0' || ch > '9');
do
{
Num = Num * 10 + ch - '0';
ch = getchar();
}
while(ch >= '0' && ch <= '9');
return Num * Flag;
}
int Next[MAX_SIZE], X[MAX_SIZE];
int N, K, M, Ans;
struct Matrix
{
int A[MAX_SIZE][MAX_SIZE];
int n, m;
inline Matrix operator * (Matrix const &a) const
{
Matrix temp;
memset(&temp, 0, sizeof(Matrix));
temp.n = n;
temp.m = a.m;
for(int i = 0; i <= temp.n; ++i)
for(int j = 0; j <= temp.m; ++j)
for(int k = 0; k <= m; ++k)
temp.A[i][j] = (temp.A[i][j] + A[i][k] * a.A[k][j]) % Mod;
return temp;
}
inline void operator *= (Matrix const &a)
{
*this = (*this) * a;
}
inline Matrix operator ^ (const int k)
{
Matrix ans, K1;
memset(&ans, 0, sizeof(Matrix));
K1 = *this;
ans.n = ans.m = n;
for(int i = 0; i <= n; ++i)
ans.A[i][i] = 1;
int temp = k;
while(temp)
{
if(temp & 1)
ans *= K1;
temp >>= 1;
K1 *= K1;
}
return ans;
}
}a, DP;
int main()
{
cin >> N >> M >> K;
char ch = getchar();
while(ch < '0' || ch > '9')
ch = getchar();
for(int i = 1; i <= M; ++i)
X[i] = ch - '0', ch = getchar();
X[M + 1] = 10;
int temp = 0;
for(int i = 2; i <= M; ++i)
{
while(temp && X[i] != X[temp + 1])
temp = Next[temp];
if(X[i] == X[temp + 1])
Next[i] = ++temp;
}
a.n = a.m = M - 1;
for(int i = 0; i < M; ++i)
{
for(int j = 0; j < 10; ++j)
{
int temp = i;
while(temp && X[temp + 1] != j)
temp = Next[temp];
if(X[temp + 1] == j)
++temp;
++a.A[i][temp];
}
}
DP.A[0][0] = 1;
DP.n = 0;
DP.m = M - 1;
DP *= (a ^ N);
for(int i = 0; i < M; ++i)
Ans = (Ans + DP.A[0][i]) % Mod;
cout << Ans << endl;
return 0;
}
POJ2778:
#include "cstdio"
#include "cstdlib"
#include "iostream"
#include "algorithm"
#include "cstring"
#include "queue"
using namespace std;
#define MAX_SIZE 105
#define INF 0x3F3F3F3F
#define Eps
#define Mod 100000
inline int Get_Int()
{
int Num = 0, Flag = 1;
char ch;
do
{
ch = getchar();
if(ch == '-')
Flag *= -1;
}
while(ch < '0' || ch > '9');
do
{
Num = Num * 10 + ch - '0';
ch = getchar();
}
while(ch >= '0' && ch <= '9');
return Num * Flag;
}
class Node
{
public:
Node *Fail, *Next[4];
int Num;
bool Flag;
}*Root, *Empty;
class Matrix
{
public:
int N, M;
long long A[MAX_SIZE][MAX_SIZE];
inline Matrix operator * (Matrix const &a) const
{
Matrix temp;
memset(&temp, 0, sizeof(temp));
temp.N = N;
temp.M = a.M;
for(int i = 1; i <= N; ++i)
for(int j = 1; j <= temp.M; ++j)
for(int k = 1; k <= M; ++k)
temp.A[i][j] = (temp.A[i][j] + A[i][k] * a.A[k][j]) % Mod;
return temp;
}
inline Matrix operator ^ (int k) const
{
Matrix a = *this, Ans;
memset(&Ans, 0, sizeof(Ans));
Ans.N = Ans.M = N;
for(int i = 1; i <= N; ++i)
Ans.A[i][i] = 1;
while(k)
{
if(k & 1)
Ans = Ans * a;
k >>= 1;
a = a * a;
}
return Ans;
}
}A, Ans;
int N, M, Total;
bool Visit[MAX_SIZE];
char Word[MAX_SIZE];
inline Node* New()
{
Node *x = (Node*)(malloc(sizeof(Node)));
memset(x, 0, sizeof(Node));
x -> Num = Total++;
return x;
}
inline int Get(char ch)
{
if(ch == 'A')
return 0;
else if(ch == 'G')
return 1;
else if(ch == 'C')
return 2;
else
return 3;
}
inline void Build_Trie()
{
Empty = New();
Root = New();
for(int i = 0; i < 4; ++i)
Empty -> Next[i] = Root;
Root -> Fail = Empty;
for(int i = 1; i <= M; ++i)
{
Node *Now = Root;
scanf("%s", Word);
for(int j = 0, temp = strlen(Word), To; j < temp; ++j, Now = Now -> Next[To])
{
To = Get(Word[j]);
if(!Now -> Next[To])
Now -> Next[To] = New();
}
Now -> Flag = true;
}
}
inline void Build_ACAM()
{
queue<Node*> Queue;
Queue.push(Root);
while(!Queue.empty())
{
Node *Now = Queue.front(), *temp;
Queue.pop();
if(Now -> Fail -> Flag)
Now -> Flag = true;
for(int i = 0; i < 4; ++i)
if(Now -> Next[i])
{
Now -> Next[i] -> Fail = Now -> Fail -> Next[i];
Queue.push(Now -> Next[i]);
}
else
Now -> Next[i] = Now -> Fail -> Next[i];
}
}
inline void Get_Matrix()
{
queue<Node*> Queue;
Queue.push(Root);
Visit[Root -> Num] = true;
while(!Queue.empty())
{
Node *Now = Queue.front(), *temp;
Queue.pop();
if(Now -> Flag)
continue;
for(int i = 0; i < 4; ++i)
{
if(Now -> Next[i] -> Flag)
continue;
++A.A[Now -> Num][Now -> Next[i] -> Num];
if(!Visit[Now -> Next[i] -> Num])
{
Visit[Now -> Next[i] -> Num] = true;
Queue.push(Now -> Next[i]);
}
}
}
A.N = A.M = Total - 1;
}
int main()
{
cin >> M >> N;
Build_Trie();
Build_ACAM();
Get_Matrix();
Ans.N = 1;
Ans.M = Total - 1;
Ans.A[1][1] = 1;
Ans = Ans * (A ^ N);
long long Sum = 0;
for(int i = 1; i < Total; ++i)
Sum = (Sum + Ans.A[1][i]) % Mod;
cout << Sum << endl;
return 0;
}