题意:求不包含给定的串且长度不大于m的串的个数
思路:这题是POJ2778的加强版,方法是求出包含给定的串的个数,再用总的方法数去减这个数字,就是得到不包含给定的串的个数。
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int N=40;
const int CHAR=26;
typedef unsigned long long ll;
int Hash(char c){
return c-'a';
}
struct Trie
{
int next[N][CHAR],fail[N],end[N];
int root,L;
int newnode()
{
for(int i = 0;i < CHAR;i++)
next[L][i] = -1;
end[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0;i < len;i++)
{
int u=Hash(buf[i]);
if(next[now][u] == -1)
next[now][u] = newnode();
now = next[now][u];
}
end[now]=1;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0;i < CHAR;i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while( !Q.empty() )
{
int now = Q.front();
Q.pop();
for(int i = 0;i < CHAR;i++)
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
end[next[now][i]]|=end[next[fail[now]][i]];//需注意
Q.push(next[now][i]);
}
}
}
};
char s[105];
Trie ac;
struct Mat{
ll a[40][40];
int sz;
Mat(){}
Mat(int _x):sz(_x){
for(int i=0;i<=_x;i++)
for(int j=0;j<=_x;j++)
a[i][j]=0;
}
Mat operator * (const Mat &b)const{
Mat ret(sz);
for(int i=0;i<=sz;i++)
for(int j=0;j<=sz;j++)
for(int k=0;k<=sz;k++){
ret.a[i][j]+=(ll)a[i][k]*b.a[k][j];
}
return ret;
}
Mat operator ^(int t){
Mat ret(sz);
for(int i=0;i<=sz;i++)ret.a[i][i]=1;
while(t){
if(t&1)ret=ret * *this;
t>>=1;
*this=*this * *this;
}
return ret;
}
void out(){
for(int i=0;i<=sz;i++){
for(int j=0;j<=sz;j++){
printf("%d,",a[i][j]);
}
printf("\n");
}
}
};
ll Pow(ll a,ll b){
ll ret=1;
while(b){
if(b&1)ret=ret*a;
b>>=1;
a=a*a;
}
return ret;
}
int main()
{
freopen("C_in.txt","r",stdin);
int T;
int n,m;
while(~scanf("%d%d",&n,&m))
{
ac.init();
for(int i = 1;i<=n;i++){
scanf("%s",s);
ac.insert(s);
}
ac.build();
Mat A(ac.L);
Mat B(ac.L);
for(int i=0;i<ac.L;i++){
if(ac.end[i])continue;
for(int j=0;j<CHAR;j++){
if(ac.end[ac.next[i][j]])continue;
A.a[ac.next[i][j]][i]++;
}
//A.out();
}
for(int i=0;i<=ac.L;i++)
A.a[ac.L][i]=1;
//A.out();
B.a[0][0]=1;
A=A^(m);
A=A*B;
ll ans=0;
for(int i=0;i<=ac.L;i++)
ans+=A.a[i][0];
Mat C(2);
Mat D(2);
D.a[0][0]=D.a[1][0]=1;
C.a[0][0]=1;C.a[0][1]=C.a[1][1]=26;
C=C^(m);
C=C*D;
ans=C.a[0][0]-ans;
printf("%I64u\n",ans);
}
return 0;
}