【XSY2989】字符串

题目来源:NOI2018模拟测试赛(二十六)

题解:

首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果;

一个串出现有三种情况:在前半部分,在后半部分或穿过中间;

对于前两种情况,由于n很小,可以直接在AC自动机跑状压DP,对于第三种情况特殊处理一下,就是对于所有子串的所有前缀,判断以这个前缀为结尾能否构造出这个串,有则累加答案就好了,具体见代码。

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 #define mod 998244353
10 using namespace std;
11 typedef long long ll;
12 typedef double db;
13 struct ac{
14     int fa,fail,son[2],s,t;
15 }t[200001];
16 int n,m,nw,tmp,ans=0,len,cnt=0,num[2001],f[2][2001][64];
17 char s[101];
18 void ins(char *s,int len,int id){
19     int nw=0;
20     for(int i=1;i<=len;i++){
21         if(!t[nw].son[s[i]-'0']){
22             t[nw].son[s[i]-'0']=++cnt;
23             num[cnt]=s[i]-'0';
24             t[cnt].fa=nw;
25         }
26         nw=t[nw].son[s[i]-'0'];
27     }
28     t[nw].s|=(1<<id-1);
29 }
30 void AC(){
31     queue<int>q;
32     for(int i=0;i<=1;i++){
33         if(t[0].son[i]){
34             q.push(t[0].son[i]);
35             t[t[0].son[i]].fail=0;
36         }
37     }
38     while(!q.empty()){
39         int u=q.front();
40         q.pop();
41         t[u].s|=t[t[u].fail].s;
42         for(int i=0;i<=1;i++){
43             if(t[u].son[i]){
44                 t[t[u].son[i]].fail=t[t[u].fail].son[i];
45                 q.push(t[u].son[i]);
46             }else t[u].son[i]=t[t[u].fail].son[i];
47         }
48     }
49 }
50 int getfa(int u){
51     int ret=0;
52     for(int nw=u;nw;nw=t[nw].fa){
53         u=t[u].son[num[nw]^1];
54         ret|=t[u].s;
55     }
56     return ret;
57 }
58 int main(){
59     scanf("%d%d",&n,&m);
60     for(int i=1;i<=n;i++){
61         scanf("%s",s+1);
62         len=strlen(s+1);
63         ins(s,len,i);
64         reverse(s+1,s+len+1);
65         for(int j=1;j<=len;j++){
66             s[j]=((s[j]-'0')^1)+'0';
67         }
68         ins(s,len,i);
69     }
70     AC();
71     f[0][0][0]=1;
72     for(int tt=1;tt<=m;tt++){
73         nw^=1;
74         memset(f[nw],0,sizeof(f[nw]));
75         for(int i=0;i<=cnt;i++){
76             for(int j=0;j<(1<<n);j++){
77                 for(int k=0;k<=1;k++){
78                     f[nw][t[i].son[k]][j|t[t[i].son[k]].s]=(f[nw][t[i].son[k]][j|t[t[i].son[k]].s]+f[nw^1][i][j])%mod;
79                 }
80             }
81         }
82     }
83     for(int i=0;i<=cnt;i++){
84         tmp=getfa(i);
85         for(int j=0;j<(1<<n);j++){
86             if((tmp|j)==(1<<n)-1){
87                 ans=(ans+f[nw][i][j])%mod;
88             }
89         }
90     }
91     printf("%d",ans);
92     return 0;
93 }
posted @ 2018-12-04 11:11  DCDCBigBig  阅读(244)  评论(0编辑  收藏  举报