HDU 6086 Rikka with String
Rikka with String
http://acm.hdu.edu.cn/showproblem.php?pid=6086
题意:
求一个长度为2L的,包含所给定的n的串,并且满足非对称。
分析:
AC自动机+状压dp。
首先给这个n个串,建立AC自动机。然后去枚举长度为L的一个串,就可以知道另一半了。
如果给定的串完全存在于左边或者右边,那么直接往AC自动机加入这个串或者取反后的反串。如果是跨越中间,那么暴力的把所有的串,从中间切开,然后判断是否合法,加入到AC自动机上就行,如果长度枚举到了i-1的时候,这些串的状态才有用。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int mod = 998244353; 20 int ch[2500][2], sta1[2500], sta2[2500], fail[2500], q[2500], dp[2][2500][70]; 21 int Index; 22 char s[100], t[100], a[100], b[100]; 23 24 void Insert(char *s,int n,int id,bool f) { 25 int u = 0; 26 for (int i = 0; i < n; ++i) { 27 int c = s[i] - '0'; 28 if (!ch[u][c]) ch[u][c] = ++Index; 29 u = ch[u][c]; 30 } 31 if (f) sta1[u] |= (1 << id); 32 else sta2[u] |= (1 << id); 33 } 34 void build() { 35 int L = 1, R = 0; 36 for (int i = 0; i < 2; ++i) if (ch[0][i]) q[++R] = ch[0][i]; 37 while (L <= R) { 38 int u = q[L ++]; 39 for (int c = 0; c < 2; ++c) { 40 int v = ch[u][c]; 41 if (!v) { ch[u][c] = ch[fail[u]][c]; continue; } 42 int p = fail[u]; while (p && !ch[p][c]) p = fail[p]; 43 q[++R] = v; 44 fail[v] = ch[p][c]; 45 sta1[v] |= sta1[fail[v]], sta2[v] |= sta2[fail[v]]; 46 } 47 } 48 } 49 void update(char *s,int n,int id) { 50 int c1 = 0, c2 = 0, f = 0; 51 for (int i = 0; i < n - 1; ++i) { 52 c1 = c2 = f = 0; 53 for (int j = i; j >= 0; --j) a[c1 ++] = s[j];a[c1] = '\0'; 54 for (int j = i + 1; j < n; ++j) b[c2 ++] = s[j]; b[c2] = '\0'; 55 for (int j = 0; j < c1 && j < c2; ++j) if (a[j] == b[j]) { f = 1; break; } 56 if (f) continue; 57 for (int j = c1; j < c2; ++j) a[j] = b[j] == '0' ? '1' : '0'; 58 reverse(a, a + max(c1, c2)); 59 Insert(a, max(c1, c2), id, 0); // 长度为max(c1,c2)!!! 60 } 61 } 62 void init() { 63 memset(dp, 0, sizeof(dp)); 64 memset(ch, 0, sizeof(ch)); 65 memset(fail, 0, sizeof(fail)); 66 memset(sta1, 0, sizeof(sta1)); 67 memset(sta2, 0, sizeof(sta2)); 68 } 69 inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; } 70 void solve() { 71 init(); 72 int n = read(), L = read(), len; 73 for (int i = 0; i < n; ++i) { 74 scanf("%s", s); len = strlen(s); 75 Insert(s, len, i, 1); 76 for (int j = 0; j < len; ++j) t[j] = s[j]; 77 reverse(t, t + len); 78 for (int j = 0; j < len; ++j) t[j] = t[j] == '0' ? '1' : '0'; 79 Insert(t, len, i, 1); 80 update(s, len, i); 81 } 82 build(); 83 dp[0][0][0] = 1; 84 int All = (1 << n) - 1, now = 0; 85 for (int i = 0; i < L; ++i, now ^= 1) 86 for (int j = 0; j <= Index; ++j) 87 for (int s = 0; s <= All; ++s) { 88 if (dp[now][j][s] <= 0) continue; 89 for (int c = 0; c < 2; ++c) { 90 int nv = ch[j][c], ns = s | sta1[nv]; 91 if (i == L - 1) ns |= sta2[nv]; 92 add(dp[now ^ 1][nv][ns], dp[now][j][s]); 93 } 94 dp[now][j][s] = 0; 95 } 96 int ans = 0; 97 for (int i = 0; i <= Index; ++i) add(ans, dp[now][i][All]); 98 printf("%d\n",ans % mod); 99 } 100 int main() { 101 for (int T = read(); T --; ) solve(); 102 return 0; 103 }