这是一个AC自动机+dp的问题,在中间的串的处理可以枚举中断点来插入自动机内来实现,具体参见代码。
在这题上不止为何一直MLE,一直找不到结果(lyf相同写法的代码消耗内存较少),还好考虑到这题节点应该不会过多,可以少开一点节点数。
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 //const int N = 5e4 + 5; 4 //const int MAX_Tot = 6 * 20 * 20 + 6 * 20 + 100; 5 const int MAX_Tot = 500; 6 typedef long long ll; 7 const int mod = 998244353; 8 9 int T, n, L; 10 void add(int &a, int b) 11 { 12 a += b; 13 if(a >= mod) a -= mod; 14 if(a < 0) a += mod; 15 } 16 struct Aho 17 { 18 struct state 19 { 20 int nxt[2]; 21 int fail; 22 int ed, vis; 23 }stateTable[MAX_Tot]; 24 25 int size; 26 27 queue<int> que; 28 29 void init() 30 { 31 while(que.size()) que.pop(); 32 for(int i=0;i<MAX_Tot;i++) 33 { 34 memset(stateTable[i].nxt,0,sizeof(stateTable[i].nxt)); 35 stateTable[i].fail = stateTable[i].ed = stateTable[i].vis = 0; 36 } 37 size = 1; 38 } 39 40 void insert(char *s,int which,int type) 41 { 42 int n = strlen(s); 43 int now = 0; 44 for(int i=0;i<n;i++) 45 { 46 char c = s[i]; 47 if(!stateTable[now].nxt[c-'0']) 48 stateTable[now].nxt[c-'0'] = size++; 49 now = stateTable[now].nxt[c-'0']; 50 } 51 if(type == 1) stateTable[now].ed |= (1<<which); 52 else stateTable[now].vis |= (1<<which); 53 } 54 55 void build() 56 { 57 stateTable[0].fail = -1; 58 que.push(0); 59 60 while(que.size()) 61 { 62 int u = que.front();que.pop(); 63 for(int i=0;i<2;i++) 64 { 65 if(stateTable[u].nxt[i]) 66 { 67 if(u == 0) stateTable[stateTable[u].nxt[i]].fail = 0; 68 else 69 { 70 int v = stateTable[u].fail; 71 while(v != -1) 72 { 73 if(stateTable[v].nxt[i]) 74 { 75 stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i]; 76 stateTable[stateTable[u].nxt[i]].ed |= stateTable[stateTable[stateTable[u].nxt[i]].fail].ed; 77 stateTable[stateTable[u].nxt[i]].vis |= stateTable[stateTable[stateTable[u].nxt[i]].fail].vis; 78 break; 79 } 80 v = stateTable[v].fail; 81 } 82 if(v == -1) stateTable[stateTable[u].nxt[i]].fail = 0; 83 } 84 que.push(stateTable[u].nxt[i]); 85 } 86 /*****建立自动机nxt指针*****/ 87 else 88 { 89 if(u == 0) stateTable[u].nxt[i] = 0; 90 else 91 { 92 int p = stateTable[u].fail; 93 while(p != -1 && stateTable[p].nxt[i] == 0) p = stateTable[p].fail; 94 if(p == -1) stateTable[u].nxt[i] = 0; 95 else stateTable[u].nxt[i] = stateTable[p].nxt[i]; 96 } 97 } 98 /*****建立自动机nxt指针*****/ 99 } 100 } 101 } 102 103 int dp[110][MAX_Tot][1<<6]; 104 void solve() 105 { 106 memset(dp,0,sizeof dp); 107 dp[0][0][0] = 1; 108 for(int i=1;i<=L;i++) 109 { 110 for(int j=0;j<size;j++) 111 { 112 for(int k=0;k<(1<<n);k++) 113 { 114 for(int ch=0;ch<2;ch++) 115 { 116 int now = stateTable[j].nxt[ch]; 117 int nowS = stateTable[now].ed; 118 add(dp[i][now][k|nowS], dp[i-1][j][k]); 119 } 120 } 121 } 122 } 123 int ans = 0; 124 for(int i=0;i<size;i++) 125 { 126 for(int j=0;j<(1<<n);j++) 127 { 128 if((stateTable[i].vis | j) == (1<<n)-1) 129 { 130 add(ans, dp[L][i][j]); 131 } 132 } 133 } 134 printf("%d ",ans); 135 } 136 }aho; 137 char s[50],t[50]; 138 void work(int fenge,int which) 139 { 140 int f = fenge; 141 int you = fenge + 1; 142 bool can = 1; 143 int len = strlen(s); 144 while(1) 145 { 146 if(s[fenge] == s[you]) 147 { 148 can = 0; 149 break; 150 } 151 fenge--; you++; 152 if(fenge < 0 || you >= len) break; 153 } 154 if(!can) return ; 155 fenge = f; 156 if((fenge+1) * 2 <= len) 157 { 158 for(int i=0;i<len-(fenge+1);i++) t[i] = s[len-1-i] == '1' ? '0' : '1'; t[len-(fenge+1)] = 0; 159 aho.insert(t,which,2); 160 } 161 else 162 { 163 for(int i=0;i<=fenge;i++) t[i] = s[i]; t[fenge+1] = 0; 164 aho.insert(t,which,2); 165 } 166 } 167 168 int main() 169 { 170 scanf("%d",&T); 171 while(T--) 172 { 173 aho.init(); 174 scanf("%d%d",&n,&L); 175 for(int i=0;i<n;i++) 176 { 177 scanf("%s",s); 178 int len = strlen(s); 179 aho.insert(s,i,1); 180 for(int j=0;j<len;j++) t[j] = s[len-j-1] == '1' ? '0' : '1'; t[len] = 0; 181 aho.insert(t,i,1); 182 for(int j=0;j<len-1;j++) work(j,i); 183 } 184 aho.build(); 185 aho.solve(); 186 } 187 return 0; 188 }