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] = '