题面
其实我的写法有些复杂。。。
考虑一个反对称串
T
前
先考虑前两种情况,想到建出AC自动机再状压DP,我们从第
m
位往前DP,AC自动机上要建出每个给定串
具体地,设计状态
f[i][j][s][0/1]
表示DP了
i
位,在AC自动机上
其实直接从前往后DP,DP完之后在把分在中点两边的串的标记或上去会好写些。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=998244353;
const int maxp=3010;
int n,m,cnt,cs[110],len[8],a[maxp][2],fa[maxp],pl[maxp],uf[maxp],dl[maxp],f[2][maxp][70][2];
bool bk[maxp][2];
char s[8][110];
void ins(int *t,int len,int id,int* lab)
{
int p=0;
for(int i=1;i<=len;p=a[p][t[i]],i++)
if(!a[p][t[i]]) bk[p][t[i]]=1,a[p][t[i]]=++cnt;
lab[p]|=(1<<(id-1));
}
void check(int *t,int len,int id,int d)
{
for(int i=1;i<=len;i++)
{
if(2*d-i+1>0&&2*d-i+1<=len&&t[i]==t[2*d-i+1]) {return ;}
}
int w[110];
if(d>len/2)
{
for(int i=1;i<=d;i++)
w[i]=t[d-i+1];
ins(w,d,id,uf);
}
else
{
for(int i=d+1;i<=len;i++)
w[i-d]=(t[i]^1);
ins(w,len-d,id,uf);
}
}
void getac()
{
for(int hd=1,tl=1,v=0;hd<=tl;v=dl[++hd])
for(int ic=0;ic<=1;ic++)
if(a[v][ic])
{
int p=fa[v];
while(p&&!a[p][ic]) p=fa[p];
if(a[p][ic]!=a[v][ic]) fa[a[v][ic]]=a[p][ic],pl[a[v][ic]]|=pl[a[p][ic]];
dl[++tl]=a[v][ic];
}
else a[v][ic]=a[fa[v]][ic];
}
void dp()
{
memset(f,0,sizeof(f));
f[0][0][pl[0]|uf[0]][0]=1;
for(int i=1,v=1;i<=m;v^=1,i++)
{
memset(f[v],0,sizeof(f[v]));
for(int j=0;j<=cnt;j++)
for(int s=0;s<(1<<n);s++)
if(f[v^1][j][s][0]||f[v^1][j][s][1])
for(int ic=0;ic<=1;ic++)
{
int to=a[j][ic];
(f[v][to][ pl[to] | s ][1]+=f[v^1][j][s][1])%=mod;
if(bk[j][ic]) (f[v][to][ pl[to] | uf[to] | s ][0]+=f[v^1][j][s][0])%=mod;
else (f[v][to][ pl[to] | s ][1]+=f[v^1][j][s][0])%=mod;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
len[i]=strlen(s[i]+1);
for(int j=1;j<=len[i];j++)
cs[j]=s[i][len[i]-j+1]-'0';
ins(cs,len[i],i,pl);
for(int j=1;j<=len[i];j++)
cs[j]=((s[i][j]-'0')^1);
ins(cs,len[i],i,pl);
for(int j=1;j<=len[i];j++)
cs[j]=s[i][j]-'0';
for(int j=1;j<len[i];j++)
check(cs,len[i],i,j);
}
getac();
dp();
int ans=0;
for(int i=0;i<=cnt;i++)
(ans+=f[m&1][i][(1<<n)-1][0])%=mod,(ans+=f[m&1][i][(1<<n)-1][1])%=mod;
printf("%d",ans);
return 0;
}