中文题意

第一行给出n,第二行输入长度为n的字符串S。
第三行给出m,接下来m行每行给出一个字符串


要你把S串翻转得到新的S串,并且输出一个用某些T形成这个新的S串,题目保证有解。

Solution

我们发现字符串翻转之后只需要匹配,根据字符串匹配的规则,最快的方式就是字符串hash,可以做到
那么我们求到翻转之后新的S串个个位置的hash值。我们再去把m个有的hash值依次保存起来。
接下来,我们使用动态规划,枚举当前的下标位置,去前面找一个可以组成的下标,并且保证子串从可以被出现过的hash值填充。我们就把当前位置记录一个当前填入的hash串的hash值。
最后从n往前遍历就可以找到答案,这样看起来时间复杂度是,但是题目保证了数据范围内有解,所以,每1000个字符里面一定是有一个解的,所以就算跳表每次跳1000跑满第二个循环,我们都只有大概的复杂度。

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
#define repp(i, sta, en) for(int i=sta; i>=en; --i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;

ll n, m;
string s, t;
ull has1[N], p[N], bas = 131;
ull f[N];
map<ull, string> mp;

ull calc(int l, int r) {
    return has1[r] - has1[l - 1] * p[r - l + 1];
}

void get_ans(int x) {
    if (!x)    return;
    get_ans(x - mp[f[x]].size());
    cout << mp[f[x]] << " ";
}

void solve() {
    js;
    cin >> n;
    cin >> s;
    p[0] = 1;
    rep(i, 1, n) {
        p[i] = p[i - 1] * bas;
        has1[i] = has1[i - 1] * bas + s[i - 1];
    }
    cin >> m;
    int st = 1;
    rep(i, 1, m) {
        cin >> t;
        int len = t.size();
        ull tmp = 0;
        repp(j, len - 1, 0)
            tmp = tmp * bas + tolower(t[j]);
        mp[tmp] = t;
    }
    f[0] = 1;
    rep(i, 1, n) {
        repp(j, i, 1) {
            ull tmp = calc(j, i);
            if (f[j - 1] and mp.count(tmp)) {
                f[i] = tmp;
                break;
            }
        }
    }
    get_ans(n);
}

int main() {
    solve();
    return 0;
}