HDU - 6086 Rikka with String AC自动机 + dp
Posted cjlhy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6086 Rikka with String AC自动机 + dp相关的知识,希望对你有一定的参考价值。
前缀和后缀分别建AC自动机, 考虑从两端往中间dp
dp[ o ][ i ][ j ][ mask ] 表示放了前面和后面o个, 第一个自动机在 i 位置, 第二个自动机在 j 位置, 拥有的目标串的状态是mask的方案数。
对于跨过两端的东西, 我们最后处理就好了。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 121 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T &a, S b) a += b; if(a >= mod) a -= mod; template<class T, class S> inline void sub(T &a, S b) a -= b; if(a < 0) a += mod; template<class T, class S> inline bool chkmax(T &a, S b) return a < b ? a = b, true : false; template<class T, class S> inline bool chkmin(T &a, S b) return a > b ? a = b, true : false; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); const int M = 121; int T, n, L, mask[M][M]; char t[M]; string s[M]; int dp[2][M][M][1 << 6]; int (*f)[M][1 << 6] = dp[0]; int (*g)[M][1 << 6] = dp[1]; struct Ac // 1. init before use 2. cheke character set int ch[M][2], f[M], tot, sz, subVal; int val[M]; string str[M]; inline int newNode() tot++; f[tot] = val[tot] = 0; s[tot] = ""; memset(ch[tot], 0, sizeof(ch[tot])); return tot; void init(int _sz, int _subVal) sz = _sz; subVal = _subVal; tot = -1; newNode(); inline int idx(int c) return c - subVal; void addStr(char* s, int who) int u = 0; for(int i = 0; s[i]; i++) int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = newNode(); str[ch[u][c]] = str[u]; str[ch[u][c]].push_back(s[i]); u = ch[u][c]; val[u] |= (1 << who); void build() queue<int> que; for(int c = 0; c < sz; c++) int v = ch[0][c]; if(!v) ch[0][c] = 0; else f[v] = 0, que.push(v); while(!que.empty()) int u = que.front(); que.pop(); val[u] |= val[f[u]]; for(int c = 0; c < sz; c++) int v = ch[u][c]; if(!v) ch[u][c] = ch[f[u]][c]; else f[v] = ch[f[u]][c], que.push(v); ac[2]; int main() scanf("%d", &T); while(T--) ac[0].init(2, ‘0‘); ac[1].init(2, ‘0‘); memset(mask, 0, sizeof(mask)); scanf("%d%d", &n, &L); for(int i = 0; i < n; i++) scanf("%s", t); s[i] = t; int m = strlen(t); ac[0].addStr(t, i); reverse(t, t + m); ac[1].addStr(t, i); ac[0].build(); ac[1].build(); for(int i = 1; i <= ac[0].tot; i++) for(int j = 1; j <= ac[1].tot; j++) string L = ac[0].str[i]; string R = ac[1].str[j]; reverse(ALL(R)); string now = L + R; string tmp; for(int p = 0; p < SZ(L); p++) for(int k = 0; k < n; k++) if(SZ(s[k]) == 1) continue; tmp = now.substr(p, SZ(s[k])); if(tmp == s[k]) mask[i][j] |= 1 << k; for(int i = 0; i <= ac[0].tot; i++) for(int j = 0; j <= ac[1].tot; j++) for(int k = 0; k < (1 << n); k++) f[i][j][k] = 0; f[0][0][0] = 1; int ni, nj, nk; for(int o = 0; o < L; o++) swap(f, g); for(int i = 0; i <= ac[0].tot; i++) for(int j = 0; j <= ac[1].tot; j++) for(int k = 0; k < (1 << n); k++) f[i][j][k] = 0; for(int i = 0; i <= ac[0].tot; i++) for(int j = 0; j <= ac[1].tot; j++) for(int k = 0; k < (1 << n); k++) for(int c = 0; c < 2; c++) ni = ac[0].ch[i][c]; nj = ac[1].ch[j][c ^ 1]; nk = k | ac[0].val[ni] | ac[1].val[nj]; add(f[ni][nj][nk], g[i][j][k]); int ans = 0; for(int i = 0; i <= ac[0].tot; i++) for(int j = 0; j <= ac[1].tot; j++) for(int k = 0; k < (1 << n); k++) if((mask[i][j] | k) == (1 << n) - 1) add(ans, f[i][j][k]); printf("%d\n", ans); return 0; /* */
以上是关于HDU - 6086 Rikka with String AC自动机 + dp的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6095: Rikka with Competition