P4698
dp #状压dp #树上dp #预处理
建树,将每个子串的 设为它的最长的存在的前缀,那么原来的题转化为
对于一棵树标号,使得 为 的祖先
对于原限制,最多有 个点被影响,可以状压,这样的时间复杂度是 的,不能通过
但是上述的 个状态中有一部分不合法一直不可能被转移,可以先预处理合法的状态,每次只对这些状态转移,就可以通过了
// Author: xiaruize #define ONLINE_JUDGE #ifndef ONLINE_JUDGE bool start_of_memory_use; #else #define debug(x) #endif #include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE clock_t start_clock = clock(); #endif namespace __DEBUG_UTIL__ { using namespace std; /* Primitive Datatypes Print */ void print(const char *x) { cerr << x; } void print(bool x) { cerr << (x ? "T" : "F"); } void print(char x) { cerr << '\'' << x << '\''; } void print(signed short int x) { cerr << x; } void print(unsigned short int x) { cerr << x; } void print(signed int x) { cerr << x; } void print(unsigned int x) { cerr << x; } void print(signed long int x) { cerr << x; } void print(unsigned long int x) { cerr << x; } void print(signed long long int x) { cerr << x; } void print(unsigned long long int x) { cerr << x; } void print(float x) { cerr << x; } void print(double x) { cerr << x; } void print(long double x) { cerr << x; } void print(string x) { cerr << '\"' << x << '\"'; } template <size_t N> void print(bitset<N> x) { cerr << x; } void print(vector<bool> v) { /* Overloaded this because stl optimizes vector<bool> by using _Bit_reference instead of bool to conserve space. */ int f = 0; cerr << '{'; for (auto &&i : v) cerr << (f++ ? "," : "") << (i ? "T" : "F"); cerr << "}"; } /* Templates Declarations to support nested datatypes */ template <typename T> void print(T &&x); template <typename T> void print(vector<vector<T>> mat); template <typename T, size_t N, size_t M> void print(T (&mat)[N][M]); template <typename F, typename S> void print(pair<F, S> x); template <typename T, size_t N> struct Tuple; template <typename T> struct Tuple<T, 1>; template <typename... Args> void print(tuple<Args...> t); template <typename... T> void print(priority_queue<T...> pq); template <typename T> void print(stack<T> st); template <typename T> void print(queue<T> q); /* Template Datatypes Definitions */ template <typename T> void print(T &&x) { /* This works for every container that supports range-based loop i.e. vector, set, map, oset, omap, dequeue */ int f = 0; cerr << '{'; for (auto &&i : x) cerr << (f++ ? "," : ""), print(i); cerr << "}"; } template <typename T> void print(vector<vector<T>> mat) { int f = 0; cerr << "\n~~~~~\n"; for (auto &&i : mat) { cerr << setw(2) << left << f++, print(i), cerr << "\n"; } cerr << "~~~~~\n"; } template <typename T, size_t N, size_t M> void print(T (&mat)[N][M]) { int f = 0; cerr << "\n~~~~~\n"; for (auto &&i : mat) { cerr << setw(2) << left << f++, print(i), cerr << "\n"; } cerr << "~~~~~\n"; } template <typename F, typename S> void print(pair<F, S> x) { cerr << '('; print(x.first); cerr << ','; print(x.second); cerr << ')'; } template <typename T, size_t N> struct Tuple { static void printTuple(T t) { Tuple<T, N - 1>::printTuple(t); cerr << ",", print(get<N - 1>(t)); } }; template <typename T> struct Tuple<T, 1> { static void printTuple(T t) { print(get<0>(t)); } }; template <typename... Args> void print(tuple<Args...> t) { cerr << "("; Tuple<decltype(t), sizeof...(Args)>::printTuple(t); cerr << ")"; } template <typename... T> void print(priority_queue<T...> pq) { int f = 0; cerr << '{'; while (!pq.empty()) cerr << (f++ ? "," : ""), print(pq.top()), pq.pop(); cerr << "}"; } template <typename T> void print(stack<T> st) { int f = 0; cerr << '{'; while (!st.empty()) cerr << (f++ ? "," : ""), print(st.top()), st.pop(); cerr << "}"; } template <typename T> void print(queue<T> q) { int f = 0; cerr << '{'; while (!q.empty()) cerr << (f++ ? "," : ""), print(q.front()), q.pop(); cerr << "}"; } /* Printer functions */ void printer(const char *) {} /* Base Recursive */ template <typename T, typename... V> void printer(const char *names, T &&head, V &&...tail) { /* Using && to capture both lvalues and rvalues */ int i = 0; for (size_t bracket = 0; names[i] != '\0' and (names[i] != ',' or bracket != 0); i++) if (names[i] == '(' or names[i] == '<' or names[i] == '{') bracket++; else if (names[i] == ')' or names[i] == '>' or names[i] == '}') bracket--; cerr.write(names, i) << " = "; print(head); if (sizeof...(tail)) cerr << " ||", printer(names + i + 1, tail...); else cerr << "]\n"; } /* PrinterArr */ void printerArr(const char *) {} /* Base Recursive */ template <typename T, typename... V> void printerArr(const char *names, T arr[], size_t N, V... tail) { size_t ind = 0; for (; names[ind] and names[ind] != ','; ind++) cerr << names[ind]; for (ind++; names[ind] and names[ind] != ','; ind++) ; cerr << " = {"; for (size_t i = 0; i < N; i++) cerr << (i ? "," : ""), print(arr[i]); cerr << "}"; if (sizeof...(tail)) cerr << " ||", printerArr(names + ind + 1, tail...); else cerr << "]\n"; } } #ifndef ONLINE_JUDGE #define debug(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printer(#__VA_ARGS__, __VA_ARGS__) #define debugArr(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printerArr(#__VA_ARGS__, __VA_ARGS__) #else #define debug(...) #define debugArr(...) #endif #define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define mms(arr, n) memset(arr, n, sizeof(arr)) #define rep(i, a, n) for (int i = (a); i <= (n); ++i) #define per(i, n, a) for (int i = (n); i >= (a); --i) int max(int a, int b) { if (a > b) return a; return b; } int min(int a, int b) { if (a < b) return a; return b; } const int INF = 0x3f3f3f3f3f3f3f3f; const int MOD = 1000000007; const int N = 50 + 10; int n; string s[N]; int m, tot; int a[N], b[N]; vector<int> uni; bool hsfa[N]; int lim[100000], li[100000]; vector<int> g[N]; vector<int> vec; int dp[55][100000]; int cur[55][100000], tmp[100000]; bool check(int x, int y) { if (s[x].size() > s[y].size()) return false; return s[y].substr(0, s[x].size()) == s[x]; } void dfs(int x) { // debug(g[x]); mms(cur[x], 0); cur[x][0] = 1; for (auto v : g[x]) { dfs(v); mms(tmp, 0); for (auto msk : vec) { for (int p = msk; p; p = (p - 1) & msk) { if (!(lim[p] & (msk ^ p))) { // debug(x, v, msk, p); (tmp[msk] += cur[x][msk ^ p] * dp[v][p] % MOD) %= MOD; } } } rep(v, 0, (1 << tot) - 1)(cur[x][v] += tmp[v]) %= MOD; } rep(v, 0, (1 << tot) - 1) { dp[x][v] = cur[x][v]; } for (auto v : vec) debug(x, v, dp[x][v]); if (x) { for (auto v : vec) { rep(i, 0, tot - 1) { if ((v & (1 << i))) { // debug(x, v, i); (dp[x][v] += cur[x][v ^ (1 << i)]) %= MOD; } } } } for (auto v : vec) debug(x, v, dp[x][v]); } void solve() { cin >> n; rep(i, 1, n) cin >> s[i]; cin >> m; rep(i, 1, m) { cin >> a[i]; uni.push_back(a[i]); } cin >> m; rep(i, 1, m) { cin >> b[i]; uni.push_back(b[i]); } sort(ALL(uni)); uni.resize(unique(ALL(uni)) - uni.begin()); tot = uni.size(); rep(i, 1, m) a[i] = lower_bound(ALL(uni), a[i]) - uni.begin(); rep(i, 1, m) { b[i] = lower_bound(ALL(uni), b[i]) - uni.begin(); debug(a[i], b[i]); lim[1ll << a[i]] |= (1ll << b[i]); // lim[1ll << b[i]] |= (1ll << a[i]); li[1ll << b[i]] |= (1ll << a[i]); } rep(msk, 0, (1 << tot) - 1) { rep(i, 0, tot - 1) { if (msk & (1 << i)) { li[msk] |= li[1 << i]; lim[msk] |= lim[1 << i]; } } // debug(lim[msk]); } sort(s + 1, s + n + 1); per(i, n, 1) { rep(j, i + 1, n) { if (check(i, j) && !hsfa[j]) { g[i].push_back(j); hsfa[j] = true; } } } rep(i, 1, n) if (!hsfa[i]) g[0].push_back(i); rep(msk, 0, (1 << tot) - 1) { bool flag = false; rep(i, 1, m) flag |= ((msk & (1 << a[i])) && (!(msk & (1 << b[i])))); if (!flag) { vec.push_back(msk); } } debug(tot, vec); rep(v, 0, (1 << tot) - 1) debug(v, lim[v], li[v]); dfs(0); int res = dp[0][(1 << tot) - 1]; rep(i, 1, n - tot) res = res * i % MOD; cout << res << endl; } #ifndef ONLINE_JUDGE bool end_of_memory_use; #endif signed main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int testcase = 1; // cin >> testcase; while (testcase--) solve(); #ifndef ONLINE_JUDGE cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl; cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl; #endif return 0; }
本文作者:xiaruize's Blog
本文链接:https://www.cnblogs.com/xiaruize/p/18101828
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步