與此題類似
http://blog.csdn.net/viphong/article/details/53039419
dp遞推一樣
在它的基礎上多了一步求前綴和
solution是加多一維累計即可
最後求一個26+26^2 + 26^3 + 26^4 ...的一個快速冪相減就算是答案
對2^64取模就是 ull即可
printf+ull 是%llu。。。。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int maxlen=200;
const int maxn=6*6;
const int all_size=26;
int trie[maxn][all_size];
int fail[maxn];
int tag[maxn];
int sz;
queue<int >Q;
const int N = 40;
const long long mod=10000000;
struct Matrix
{
unsigned long long mat[N][N];
} ;
Matrix unit_matrix ;
long long n ;
int k=40;
Matrix mul(Matrix a, Matrix b) //矩陣相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
// res.mat[i][j] %= mod;
}
}
return res;
}
Matrix pow_matrix(Matrix a, long long m) //矩陣快速冪
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
struct Aho
{
int root;
int newnode()//靜態創建新節點
{
memset(trie[sz],-1,sizeof trie[sz]);
tag[sz]=0;
sz++;
return sz-1;
}
void init()//初始化
{
sz=0;
newnode();
}
void insert(char s[],int id) //插入字符串構建ac自動機,構建trie樹
{
int len=strlen(s),p=0;;
for (int i=0; i<len; i++)
{
int id=s[i]-'a';
if (trie[p][id]==-1)
trie[p][id]=newnode();
p=trie[p][id];
}
tag[p]=id; //結束標記
}
void getfail() //構建自動機fail指針
{
while(!Q.empty()) Q.pop();
fail[root]=root; //root指向root
for (int i=0; i<all_size; i++)
{
if (trie[root][i]==-1)//第一個字符不存在,指向root
trie[root][i]=root;
else //第一個字符的fail指針指向root
{
fail[trie[root][i]]=root;
Q.push(trie[root][i]); //並放入隊列,待bfs擴展
}
}
while(!Q.empty())
{
int u=Q.front(); //取擴展節點
Q.pop();
if(tag[fail[u]]) tag[u]=1; //***如果之前是tag,直接標記
for (int i=0; i<all_size; i++)//遍歷所有子節點
{
if (trie[u][i]==-1)//如果不存在,則子節點直接指向fail[u]節點的對應子節點
trie[u][i]=trie[fail[u]][i];
else //如果存在,則該節點的fail指針指向fail[u]節點對應的子節點
{
fail[trie[u][i]]=trie[fail[u]][i];
Q.push(trie[u][i]); //繼續擴展
}
}
}
}
} aho;
char s[maxlen];
char name[15][55];
Matrix get(long long n)
{
k=sz+1;
Matrix c;
memset( c.mat ,0,sizeof c.mat);
for (int i=0; i<sz; i++)
{
for (int j=0; j<26; j++)
{
if ( !tag[trie[i][j] ])
c.mat[i][trie[i][j]]++;
}
}
for (int i=0;i<=sz;i++)
c.mat[i][sz]=1;
Matrix ans = pow_matrix(c, n);
// ans=mul(ori,ans);
return ans;
}
int main()
{
/* unsigned long long s=-1;
printf("%lld\n",s);*/
k=36+1;
int i, j, t;
for(i = 0; i < k; i++)
for(j = 0; j < k; j++)
unit_matrix.mat[i][j] = 0;
for(i = 0; i < k; i++) unit_matrix.mat[i][i] = 1;
long long m;
while(cin>>n>>m)
{
aho.init();
for (int i=0; i<n; i++)
{
scanf("%s",name[i]);
aho.insert(name[i],i+1);
}
aho.getfail();
Matrix ret= get(m);
unsigned long long ans=0;
for (int j=0;j<=sz;j++)
ans=(ans+ret.mat[0][j]);
ans--;
Matrix c,ori;
k=2;
// memset( c.mat ,0,sizeof c.mat);
// memset( ori.mat ,0,sizeof ori.mat);
c.mat[0][0]=26;
c.mat[0][1]=0;
c.mat[1][0]=26;
c.mat[1][1]=1;
ori.mat[0][0]=0;
ori.mat[0][1]=1;
ori.mat[1][0]=0;
ori.mat[1][1]=0;
c=pow_matrix(c,m);
ori=mul(ori,c);
unsigned long long out=ori.mat[0][0]-ans;
// cout<<out<<endl; //AC
printf("%llu\n",out ); //WA
}
return 0;
}