矩阵快速幂、幂相加是重点
还设计到一些ac自动机的dp
#include <CSTDIO>
#include <STRING>
#include <IOSTREAM>
using namespace std;
typedef unsigned long long ULL;
const int MAXN = 60;
const int szGP = MAXN*MAXN*(sizeof (ULL));
struct tire
{
int next[26];
int fail;
int flg;
void init()
{
memset(next, 0, sizeof next);
fail = flg = 0;
}
} TREE[MAXN];
int root, index, q[40];
void inst(char *ch)
{
int a = root;
for (;*ch; ch++)
{
if (TREE[a].next[*ch-'a'] == 0)
{
TREE[++index].init();
TREE[a].next[*ch-'a'] = index;
}
a = TREE[a].next[*ch-'a'];
}
TREE[a].flg = 1;
}
void buidAC()
{
int head = 0, tail = 0;
q[head++] = root;
int i, tp;
while (head != tail)
{
tp = q[tail++];
TREE[tp].flg |= TREE[TREE[tp].fail].flg;
for (i = 0; i< 26; i++)
{
if (TREE[tp].next[i])
{
if (tp)
TREE[TREE[tp].next[i]].fail = TREE[TREE[tp].fail].next[i];
q[head++] = TREE[tp].next[i];
}
else
{
TREE[tp].next[i] = TREE[TREE[tp].fail].next[i];
}
}
}
}
struct Matrx
{
ULL data[MAXN][MAXN];
int mSize;
Matrx(){ mSize = index+1; }
Matrx(int n)
{
mSize = n;
memset(data, 0, szGP);
}
Matrx operator + (const Matrx & a) const
{
Matrx re(mSize);
for (int i = 0; i< mSize; ++i)
{
for (int j = 0; j< mSize; ++j)
{
re.data[i][j] = data[i][j] + a.data[i][j];
}
}
return re;
}
Matrx operator * (const Matrx &a) const
{
Matrx tp(mSize);
int i, j, k;
for (i = 0; i< mSize; ++i)
{
for (j = 0; j< mSize; ++j)
{
for (k = 0; k< mSize; ++k)
{
tp.data[i][j] += data[i][k]*a.data[k][j];
}
}
}
return tp;
}
Matrx pow(int p)
{
Matrx res = *this, tp = *this;
--p;
while (p)
{
if (p & 0x1)
res = res*tp;
tp = tp*tp;
p>>=1;
}
return res;
}
};
Matrx gp;
void getDPtmp() // 长度为1的状态转移矩阵
{
int i, j;
memset(gp.data, 0, szGP);
gp.mSize = index+1;
for ( i = 0; i<= index; i++)
{
if (TREE[i].flg)
continue;
for (j = 0; j<26; j++)
{
if (!TREE[TREE[i].next[j]].flg)
++gp.data[i][TREE[i].next[j]];
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int n, l;
int i, j;
char tpcha[10];
while (scanf("%d%d", &n, &l) == 2)
{
index =root = 0;
TREE[0].init();
for (i = 0; i< n; ++i)
{
scanf("%s", tpcha);
inst(tpcha);
}
buidAC();
getDPtmp();
Matrx as(2);
as.data[0][0] = 26;as.data[0][1] = 0;
as.data[1][0] = 1;as.data[1][1] = 1;
Matrx bs = as.pow(l);
ULL res = bs.data[0][0] + bs.data[1][0] - 1;
Matrx cs(2*index+2);
for (i = 0; i<=index; ++i)
{
for (j = 0; j<= index; ++j)
{
cs.data[i][j] = gp.data[i][j];
cs.data[i][j+index+1] = 0;
}
cs.data[i+index+1][i] = 1;
cs.data[i+index+1][i+index+1] = 1;
}
Matrx ds = cs.pow(l);
ULL cnt = 0;
for (i = 0; i<= index; ++i)
{
cnt = cnt + ds.data[0][i] + ds.data[index+1][i];
}
--cnt;
res-=cnt;
cout<<res<<endl;
}
return 0;
}