有之前的铺垫这题感觉好做多了。。
跟之前不同的就在于对称轴节点要特殊标记
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=2e3+7; const long long mod=998244353; const int sigma=2; char s[1111]; ll dp[2][2500][(1<<7)];//滚动i int n,L; struct automata{ int ch[maxn][sigma]; int val1[maxn],val2[maxn];//完整串,中轴串 int f[maxn]; int sz; int idx(char x){return x-'0';} int newnode(){ memset(ch[sz],0,sizeof(ch[sz])); f[sz]=val1[sz]=val2[sz]=0; return sz++; } void init(){ sz=0; newnode(); } void insert1(char *s,int v){ int u=0; int len=strlen(s); for(int i=0;i<len;i++){ int id=idx(s[i]);//s[i]-'a'; if(!ch[u][id])ch[u][id]=newnode(); u=ch[u][id]; } val1[u]|=(1<<v); } void insert2(char *s,int v){ int len=strlen(s); int u=0; for(int i=0;i<len;i++){ int id=idx(s[i]); if(!ch[u][id])ch[u][id]=newnode(); u=ch[u][id]; } val2[u]|=(1<<v); } void build(){ queue<int>q; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); val1[u]|=val1[f[u]];val2[u]|=val2[f[u]]; for(int i=0;i<sigma;i++){ int v=ch[u][i]; if(!v)ch[u][i]=ch[f[u]][i]; else q.push(v); if(u&&v)f[v]=ch[f[u]][i]; } } } void work(){ memset(dp,0,sizeof dp); dp[0][0][0]=1; for(int i=0;i<L;i++){ for(int j=0;j<sz;j++){ for(int S=0;S<(1<<n);S++){ if(dp[i%2][j][S]<=0)continue; for(int k=0;k<2;k++){ int ni=i+1,nj=ch[j][k],nS=S|val1[nj]; if(i==L-1)nS|=val2[nj]; dp[ni%2][nj][nS]=(dp[ni%2][nj][nS]+dp[i%2][j][S])%mod; } dp[i%2][j][S]=0; } } } ll ans=0; for(int i=0;i<sz;i++){ ans=(ans+dp[L%2][i][(1<<n)-1])%mod; } printf("%lld ",ans); } }ac; char t[30]; char buf[maxn]; int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&L); ac.init(); for(int i=0;i<n;i++){ scanf("%s",s);int len=strlen(s); ac.insert1(s,i); for(int j=0;j<len;j++)t[j]=s[len-1-j]=='0'?'1':'0'; t[len]=' ';ac.insert1(t,i); for(int j=0;j<len-1;j++){ //对称轴枚举,s[j]在左侧 string s1="",s2=""; for(int k=j;k>=0;k--)s1+=s[k]; for(int k=j+1;k<len;k++)s2+=s[k]; bool flag=true;int len1=s1.length(),len2=s2.length(); for(int k=0;k<len1&&k<len2;k++){ if(s1[k]==s2[k]){flag=false;break;} //反称测试 } if(!flag)continue; reverse(s1.begin(),s1.end()); for(int k=(j+1)*2;k<len;k++){ s1=(s[k]=='0'?'1':'0')+s1; } strcpy(buf,s1.c_str());ac.insert2(buf,i); } } ac.build(); ac.work(); } }