题意:中文题
题解思路:首先要做这题得先去做POJ2778,然后你知道那么长度不超过m的方案数就是26+26^2+…+26^m减去矩阵(M+M^2+…M^m)第一行的总和,因为该题取摸2^64直接用
unsigned long long 即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef unsigned long long ul;
const int mx = 105;
struct mat{
ul a[35][35];
};
mat M,I;
struct trie{
int ch[mx][26];
int f[mx];
int v[mx];
int sz;
void init(){
memset(ch[0],0,sizeof(ch[0]));
memset(f,0,sizeof(f));
memset(v,0,sizeof(v));
sz = 1;
}
int idx(char c){
return c-'a';
}
void insert(char *s){
int len = strlen(s);
int u = 0;
for(int i = 0; i < len; i++){
int d = idx(s[i]);
if(!ch[u][d]){
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][d] = sz++;
}
u = ch[u][d];
}
v[u] = 1;
}
void getfail(){
queue<int>q;
for(int d = 0; d < 26; d++){
if(!ch[0][d])
continue;
int ret = ch[0][d];
f[ret] = 0;
q.push(ret);
}
while(!q.empty()){
int u = q.front();
//cout<<u<<endl;
q.pop();
if(v[f[u]])
v[u] = 1;
for(int d = 0; d < 26; d++){
if(!ch[u][d]){
ch[u][d] = ch[f[u]][d];
continue;
}
int ret = ch[u][d];
f[ret] = ch[f[u]][d];
q.push(ret);
}
}
}
void getmat(){
memset(I.a,0,sizeof(I.a));
memset(M.a,0,sizeof(M.a));
for(int u = 0; u < sz; u++){
I.a[u][u] = 1;
for(int d = 0; d < 26; d++)
if(!v[u] && !v[ch[u][d]])
M.a[u][ch[u][d]]++;
}
}
ul A(int n){
ul ans = 1;
ul x = 26;
while(n){
if(n&1) ans = ans*x;
x = x*x;
n /= 2;
}
return ans;
}
mat add(mat x,mat y){
mat z;
for(int i = 0; i < sz; i++)
for(int j = 0; j < sz; j++)
z.a[i][j] = x.a[i][j]+y.a[i][j];
return z;
}
mat calc(mat x,mat y){
mat z;
for(int i = 0; i < sz; i++)
for(int j = 0; j < sz; j++){
z.a[i][j] = 0;
for(int k = 0; k < sz; k++)
z.a[i][j] += x.a[i][k]*y.a[k][j];
}
return z;
}
mat quick(int n){
mat ans = I;
mat x = M;
// cout<<n<<endl;
while(n){
if(n&1) ans = calc(ans,x);
x = calc(x,x);
n /= 2;
}
return ans;
}
ul S(int n){
if(n == 1) return 26;
if(n&1) return (1+A(n/2+1))*S(n/2)+A(n/2+1);
else return (1+A(n/2))*S(n/2);
}
mat SUM(int n){
if(n == 1) return M;
if(n&1) return add(calc(add(I,quick(n/2+1)),SUM(n/2)),quick(n/2+1));
else return calc(add(I,quick(n/2)),SUM(n/2));
}
ul getans(int n){
ul ans = S(n);
// cout<<n<<endl;
// cout<<ans<<endl;
// cout<<sz<<endl;
mat sum = SUM(n);
for(int i = 0; i < sz; i++)
ans -= sum.a[0][i];
// cout<<ans<<endl;
return ans;
}
}word;
char s[mx];
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
word.init();
for(int i = 1; i <= n; i++){
scanf("%s",s);
word.insert(s);
}
word.getfail();
word.getmat();
cout<<word.getans(m)<<endl;
}
return 0;
}