P4698

dp #状压dp #树上dp #预处理

建树,将每个子串的 \(fa\) 设为它的最长的存在的前缀,那么原来的题转化为
对于一棵树标号,使得 \(a_i\)\(b_i\) 的祖先

对于原限制,最多有 \(16\) 个点被影响,可以状压,这样的时间复杂度是 \(\mathcal{O}(3^{16}n)\) 的,不能通过

但是上述的 \(2^{16}\) 个状态中有一部分不合法一直不可能被转移,可以先预处理合法的状态,每次只对这些状态转移,就可以通过了

// 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;
}
posted @ 2024-03-28 15:27  xiaruize  阅读(10)  评论(0)    收藏  举报