思路:本题和POJ2778几乎是一样的,所以可以借鉴那一道题的思路。首先求出长度不超过n的不包含任何词根的单词数,然后用总的单词数减去这种情况即可。
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<iostream>
#include<set>
#include<map>
#include<cmath>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int inf = 1e9 + 10;
const int maxnode = 35;
const int sigma_size = 26;
const int maxn = 35;
char T[maxn], s[4010];
char *p;
struct Matrix
{
int r, c;
ULL a[maxn][maxn];
void init(int r, int c, ULL x) {
this->r = r;
this->c = c;
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++)
a[i][j] = x;
}
};
Matrix E;
Matrix operator + (const Matrix &A, const Matrix &B)
{
int r = A.r, c = A.c;
Matrix C; C.init(r, c, 0);
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++)
C.a[i][j] = A.a[i][j] + B.a[i][j];
return C;
}
Matrix operator * (const Matrix &A, const Matrix &B)
{
int r = A.r, c = B.c;
Matrix C; C.init(r, c, 0);
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++)
for(int k = 1; k <= B.r; k++)
C.a[i][j] = A.a[i][k] * B.a[k][j] + C.a[i][j];
return C;
}
Matrix Pow(Matrix A, LL p)
{
Matrix res = E;
while(p)
{
if(p & 1) res = res * A;
p >>= 1;
A = A * A;
}
return res;
}
ULL Pow(ULL a, LL p)
{
if(!p) return 1;
ULL ans = Pow(a, p/2);
ans *= ans;
if(p & 1) ans *= a;
return ans;
}
struct AC
{
int ch[maxnode][sigma_size];
int val[maxnode];
int f[maxnode];
int sz;
int idx(char c) { return c - 'a'; }
void init()
{
memset(ch[0], 0, sizeof ch[0]);
sz = 1;
memset(val,0,sizeof val);
}
void insert(char *s)
{
int n = strlen(s), u = 0;
for(int i = 0; i < n; i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz], 0, sizeof ch[sz]);
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = 1;
}
int getFail()
{
queue<int> q;
f[0] = 0;
for(int c = 0; c < sigma_size; c++)
{
int u = ch[0][c];
if(u) { f[u] = 0; q.push(u); }
}
while(!q.empty())
{
int r = q.front(); q.pop();
for(int c = 0; c < sigma_size; c++)
{
int u = ch[r][c];
if(!u) { ch[r][c] = ch[f[r]][c]; continue; }
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
val[u] |= val[f[u]];
}
}
return 0;
}
Matrix getMatrix()
{
Matrix A;
A.init(sz, sz, 0);
E.init(sz, sz, 0);
for(int i = 1; i <= sz; i++) E.a[i][i] = 1;
for(int i = 0; i < sz; i++)
for(int j = 0; j < sigma_size; j++)
{
int u = i, v = ch[i][j];
if(!val[v]) ++A.a[u+1][v+1];
}
return A;
}
}ac;
ULL Sigma(ULL a, LL p)
{
if(p == 0) return 1;
if(p == 1) return a;
LL ans = Sigma(a, p/2);
ans = (ULL(1) + Pow(a, p/2)) * ans;
if(p & 1) ans += Pow(a, p);
return ans;
}
Matrix Sigma(Matrix A, LL p)
{
if(p == 1) return A;
if(p == 0) return E;
Matrix Ans = Sigma(A, p/2);
Ans = (E + Pow(A, p/2)) * Ans;
if(p & 1) Ans = Ans + Pow(A, p);
return Ans;
}
int main()
{
int n; ULL l;
char s[100];
while(cin >> n >> l)
{
ac.init();
for(int i = 1; i <= n; i++)
{
scanf("%s", s);
ac.insert(s);
}
ac.getFail();
Matrix A = ac.getMatrix();
A = Sigma(A, l);
ULL ans = Sigma(26, l);
for(int i = 1; i <= ac.sz; i++)
{
ans -= A.a[1][i];
}
cout << ans << endl;
}
return 0;
}