HDU 2243 AC自动机
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2243
题目大意:字母表为a~z,给n=5个词根,问长度不超过L=2^32的单词(不要问为什么有这么长的单词,就是有这么长)至少包含一个词根有多少个?
把长度为不超过L的单词数和加起来,再减去一个词根都不包含的数量。一个词根都不包含的数量的求法跟上题相同。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#define X first
#define Y second
#define sqr(x) (x)*(x)
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
const double PI = acos(-1.0);
map<int, int>::iterator it;
typedef long long LL ;
typedef unsigned long long uLL;
template<typename T> void checkmin(T &x, T y) {x = min(x, y);}
template<typename T> void checkmax(T &x, T y) {x = max(x, y);}
const int MAX_NODE = 26;
const int CHILD_NUM = 26;
class Matrix {
public:
uLL d[MAX_NODE][MAX_NODE];
int m;
Matrix() {}
Matrix(int _m): m(_m) {};
void Set_Zero() {
memset(d, 0, sizeof(d));
}
void Set_One() {
Set_Zero();
for(int i = 0; i < m; ++i)d[i][i] = 1;
}
Matrix operator +(Matrix a) {
Matrix ret(m);
for(int i = 0; i < m; ++i)for(int j = 0; j < m; ++j)ret.d[i][j] = d[i][j] + a.d[i][j];
return ret;
}
Matrix operator *(Matrix a) {
Matrix ret(m);
ret.Set_Zero();
for(int i = 0; i < m; ++i) {
for(int k = 0; k < m; ++k) {
if(d[i][k] == 0)continue;
for(int j = 0; j < m; ++j) {
ret.d[i][j] += d[i][k] * a.d[k][j];
}
}
}
return ret;
}
Matrix Power(LL n) {
Matrix a(m), b(m);
a = *this;
b.Set_One();
while(n) {
if(n & 1)b = b * a;
a = a * a;
n >>= 1;
}
return b;
}
Matrix Get_Psum(LL n) {
Matrix ret;
if(n == 1)return *this;
if(n & 1) {
ret = Get_Psum(n / 2);
ret = ret + ret * Power(n / 2) + Power(n);
}
else {
ret = Get_Psum(n / 2);
ret = ret + ret * Power(n / 2);
}
return ret;
}
void pf() {
for(int i = 0; i < m; ++i) {
for(int j = 0; j < m; ++j) {
printf("%3d", d[i][j]);
} puts("");
}
}
};
class ACAutomaton {
public:
int chd[MAX_NODE][CHILD_NUM];
int val[MAX_NODE];
int ID[126];
int Q[MAX_NODE];
int fail[MAX_NODE];
int sz;
void Initialize() {
fail[0] = 0;
for(int i = 0; i < 26; ++i) {
ID['a'+i] = i;
}
}
void Reset() {
sz = 1;
memset(chd[0], -1, sizeof(chd[0]));
}
void Insert(char *s) {
int q = 0;
for(; *s; ++s) {
int c = ID[*s];
if(chd[q][c] == -1) {
memset(chd[sz], -1, sizeof(chd[sz]));
val[sz] = 0;
chd[q][c] = sz++;
}
q = chd[q][c];
}
val[q] = 1;
}
void Construct() {
int *s = Q, *e = Q;
for(int i = 0; i < CHILD_NUM; ++i) {
if(~chd[0][i]) {
fail[ chd[0][i] ] = 0;
*s++ = chd[0][i];
}
else chd[0][i] = 0;
}
while(s != e) {
int r = *e++;
for(int i = 0; i < CHILD_NUM; ++i) {
int &u = chd[r][i];
int v = fail[r];
if(~u) {
*s++ = u;
fail[u] = chd[v][i];
val[u] |= val[ fail[u] ];
}
else u = chd[v][i];
}
}
}
Matrix Get_Matrix() {
Matrix ret(sz);
ret.Set_Zero();
for(int i = 0; i < sz; ++i) {
if(val[i])continue;
for(int j = 0; j < CHILD_NUM; ++j) {
if(val[ chd[i][j] ])continue;
++ret.d[i][ chd[i][j] ];
}
}
return ret;
}
} AC;
const uLL K = 26;
uLL Power(uLL x, LL n) {
uLL a = x, b = 1;
while(n) {
if(n & 1)b *= a;
a *= a;
n >>= 1;
}
return b;
}
uLL Get_PS(LL n) {
//cout<<n<<endl;
if(n == 1)return K;
uLL ret, a, b;
if(n & 1) {
ret = Get_PS(n / 2);
ret = ret + ret * Power(K, n / 2) + Power(K, n);
}
else {
ret = Get_PS(n / 2);
ret = ret + ret * Power(K, n / 2);
}
return ret;
}
char s[7];
int main() {
int n;
uLL L;
AC.Initialize();
while(~scanf("%d%I64u", &n, &L)) {
uLL sum = 0;
uLL e = 1;
AC.Reset();
sum = Get_PS(L);
//printf("%I64u\n",sum);
for(uLL i = 0; i < n; ++i) {
scanf("%s", s);
AC.Insert(s);
}
AC.Construct();
Matrix a = AC.Get_Matrix();
//a.pf();
Matrix b = a.Get_Psum(L) ;
uLL res = 0;
for(int j = 0; j < b.m; ++j) {
res += b.d[0][j];
}
res = sum - res;
printf("%I64u\n", res);
}
return 0;
}

浙公网安备 33010602011771号