题目链接:Rikka with String
题意:给定
n
个
题解:我们先考虑一个简化版的问题:所有长度为
L
的字符串中出现所有给定字符串的种类数。这就是一个基本的AC自动机上
dp[i+1][p][state|(1<<k)]+=dp[i][j][state]
那么对于原问题来说,我们可以分情况讨论:
1 .字符串全部在
2 .字符串一部分在
3 .字符串全部在
我们将上述三种情况分类讨论,然后建立AC自动机,并在上面做上面写的
#include <bits/stdc++.h>
using namespace std;
const int N = 245;
const int M = 2;
int id,son[N][M],fail[N],ifo1[N],ifo2[N],q[N];
void Ist(const char* s,int info,bool ps){
int x=0,y;
for(int i=0;s[i];i++){
y=s[i]-'0';
if(!son[x][y])
son[x][y]=++id;
x=son[x][y];
}
ps?ifo1[x]|=1<<info:ifo2[x]|=1<<info;
}
void Build(){
int hd=0,tl=0,x;
for(int i=0;i<2;i++)
if(son[0][i])
q[tl++]=son[0][i];
while(hd!=tl){
x=q[hd++];
for(int i=0;i<2;i++)
if(son[x][i]){
q[tl++]=son[x][i];
fail[son[x][i]]=son[fail[x]][i];
ifo1[son[x][i]]|=ifo1[son[fail[x]][i]];
ifo2[son[x][i]]|=ifo2[son[fail[x]][i]];
}else
son[x][i]=son[fail[x]][i];
}
}
const long long MOD = 998244353;
long long dp[2][N][110];
char s[25],t[25];
int main(){
int T,len;
scanf("%d",&T);
while(T--){
int n,l;
id=0;
memset(son,0,sizeof son);
fill(fail,fail+N,0);
fill(ifo1,ifo1+N,0);
fill(ifo2,ifo2+N,0);
scanf("%d %d",&n,&l);
for(int i=0;i<n;i++){
scanf(" %s",s);
Ist(s,i,true);
len=strlen(s);
for(int j=0;j<len;j++){
bool ck=true;
for(int k=j;k<min(len,j*2);k++)
if(s[k]==s[2*j-k-1]){
ck=false;
break;
}
if(ck){
if(j*2<len){
for(int k=len-1;k>=j;k--)
t[len-1-k]=(s[k]=='0'?'1':'0');
t[len-j]='\0';
}else{
for(int k=0;k<j;k++)
t[k]=s[k];
t[j]='\0';
}
if(!j)
Ist(t,i,true);
else
Ist(t,i,false);
}
}
}
Build();
memset(dp,0,sizeof dp);
dp[0][0][0]=1;
long long ans=0;
for(int i=0;i<l;i++)
for(int j=0;j<=id;j++)
for(int k=0;k<(1<<n);k++)
if(dp[i%2][j][k]){
for(int p=0;p<2;p++){
int ps=son[j][p];
int stt=k|ifo1[ps];
if(i+1==l)
stt|=ifo2[ps];
dp[(i+1)%2][ps][stt]=
(dp[(i+1)%2][ps][stt]+dp[i%2][j][k])%MOD;
}
dp[i%2][j][k]=0;
}
for(int i=0;i<=id;i++)
ans=(ans+dp[l%2][i][(1<<n)-1])%MOD;
printf("%lld\n",ans);
}
return 0;
}