結果

問題 No.2231 Surprising Flash!
ユーザー 👑 hitonanodehitonanode
提出日時 2023-02-24 23:04:06
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 350 ms / 4,000 ms
コード長 10,979 bytes
コンパイル時間 4,914 ms
コンパイル使用メモリ 246,784 KB
実行使用メモリ 63,664 KB
最終ジャッジ日時 2023-09-03 02:53:55
合計ジャッジ時間 16,472 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 3 ms
4,380 KB
testcase_02 AC 16 ms
4,384 KB
testcase_03 AC 288 ms
4,380 KB
testcase_04 AC 10 ms
4,380 KB
testcase_05 AC 19 ms
4,384 KB
testcase_06 AC 25 ms
4,380 KB
testcase_07 AC 2 ms
4,384 KB
testcase_08 AC 7 ms
4,384 KB
testcase_09 AC 1 ms
4,380 KB
testcase_10 AC 5 ms
4,380 KB
testcase_11 AC 303 ms
54,424 KB
testcase_12 AC 301 ms
63,664 KB
testcase_13 AC 305 ms
63,524 KB
testcase_14 AC 272 ms
50,452 KB
testcase_15 AC 303 ms
54,372 KB
testcase_16 AC 289 ms
6,132 KB
testcase_17 AC 309 ms
9,040 KB
testcase_18 AC 317 ms
50,608 KB
testcase_19 AC 313 ms
50,668 KB
testcase_20 AC 315 ms
50,664 KB
testcase_21 AC 315 ms
50,656 KB
testcase_22 AC 310 ms
50,604 KB
testcase_23 AC 311 ms
50,652 KB
testcase_24 AC 316 ms
50,080 KB
testcase_25 AC 312 ms
50,072 KB
testcase_26 AC 315 ms
50,080 KB
testcase_27 AC 312 ms
50,068 KB
testcase_28 AC 314 ms
50,308 KB
testcase_29 AC 339 ms
54,568 KB
testcase_30 AC 350 ms
54,588 KB
testcase_31 AC 344 ms
54,564 KB
testcase_32 AC 344 ms
54,572 KB
testcase_33 AC 342 ms
54,556 KB
testcase_34 AC 280 ms
54,368 KB
testcase_35 AC 283 ms
54,388 KB
testcase_36 AC 281 ms
54,432 KB
testcase_37 AC 280 ms
54,440 KB
testcase_38 AC 282 ms
54,372 KB
testcase_39 AC 144 ms
8,964 KB
testcase_40 AC 102 ms
9,188 KB
testcase_41 AC 2 ms
4,380 KB
testcase_42 AC 1 ms
4,380 KB
testcase_43 AC 2 ms
4,380 KB
testcase_44 AC 61 ms
4,384 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <deque>
#include <forward_list>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using lint = long long;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(20); }; } fast_ios_;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define IFOR(i, begin, end) for(int i=(end)-1,i##_begin_=(begin);i>=i##_begin_;i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)
template <typename T, typename V>
void ndarray(vector<T>& vec, const V& val, int len) { vec.assign(len, val); }
template <typename T, typename V, typename... Args> void ndarray(vector<T>& vec, const V& val, int len, Args... args) { vec.resize(len), for_each(begin(vec), end(vec), [&](T& v) { ndarray(v, val, args...); }); }
template <typename T> bool chmax(T &m, const T q) { return m < q ? (m = q, true) : false; }
template <typename T> bool chmin(T &m, const T q) { return m > q ? (m = q, true) : false; }
const std::vector<std::pair<int, int>> grid_dxs{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int floor_lg(long long x) { return x <= 0 ? -1 : 63 - __builtin_clzll(x); }
template <class T1, class T2> T1 floor_div(T1 num, T2 den) { return (num > 0 ? num / den : -((-num + den - 1) / den)); }
template <class T1, class T2> std::pair<T1, T2> operator+(const std::pair<T1, T2> &l, const std::pair<T1, T2> &r) { return std::make_pair(l.first + r.first, l.second + r.second); }
template <class T1, class T2> std::pair<T1, T2> operator-(const std::pair<T1, T2> &l, const std::pair<T1, T2> &r) { return std::make_pair(l.first - r.first, l.second - r.second); }
template <class T> std::vector<T> sort_unique(std::vector<T> vec) { sort(vec.begin(), vec.end()), vec.erase(unique(vec.begin(), vec.end()), vec.end()); return vec; }
template <class T> int arglb(const std::vector<T> &v, const T &x) { return std::distance(v.begin(), std::lower_bound(v.begin(), v.end(), x)); }
template <class T> int argub(const std::vector<T> &v, const T &x) { return std::distance(v.begin(), std::upper_bound(v.begin(), v.end(), x)); }
template <class IStream, class T> IStream &operator>>(IStream &is, std::vector<T> &vec) { for (auto &v : vec) is >> v; return is; }

template <class OStream, class T> OStream &operator<<(OStream &os, const std::vector<T> &vec);
template <class OStream, class T, size_t sz> OStream &operator<<(OStream &os, const std::array<T, sz> &arr);
template <class OStream, class T, class TH> OStream &operator<<(OStream &os, const std::unordered_set<T, TH> &vec);
template <class OStream, class T, class U> OStream &operator<<(OStream &os, const pair<T, U> &pa);
template <class OStream, class T> OStream &operator<<(OStream &os, const std::deque<T> &vec);
template <class OStream, class T> OStream &operator<<(OStream &os, const std::set<T> &vec);
template <class OStream, class T> OStream &operator<<(OStream &os, const std::multiset<T> &vec);
template <class OStream, class T> OStream &operator<<(OStream &os, const std::unordered_multiset<T> &vec);
template <class OStream, class T, class U> OStream &operator<<(OStream &os, const std::pair<T, U> &pa);
template <class OStream, class TK, class TV> OStream &operator<<(OStream &os, const std::map<TK, TV> &mp);
template <class OStream, class TK, class TV, class TH> OStream &operator<<(OStream &os, const std::unordered_map<TK, TV, TH> &mp);
template <class OStream, class... T> OStream &operator<<(OStream &os, const std::tuple<T...> &tpl);

template <class OStream, class T> OStream &operator<<(OStream &os, const std::vector<T> &vec) { os << '['; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <class OStream, class T, size_t sz> OStream &operator<<(OStream &os, const std::array<T, sz> &arr) { os << '['; for (auto v : arr) os << v << ','; os << ']'; return os; }
template <class... T> std::istream &operator>>(std::istream &is, std::tuple<T...> &tpl) { std::apply([&is](auto &&... args) { ((is >> args), ...);}, tpl); return is; }
template <class OStream, class... T> OStream &operator<<(OStream &os, const std::tuple<T...> &tpl) { os << '('; std::apply([&os](auto &&... args) { ((os << args << ','), ...);}, tpl); return os << ')'; }
template <class OStream, class T, class TH> OStream &operator<<(OStream &os, const std::unordered_set<T, TH> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <class OStream, class T> OStream &operator<<(OStream &os, const std::deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ','; os << ']'; return os; }
template <class OStream, class T> OStream &operator<<(OStream &os, const std::set<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <class OStream, class T> OStream &operator<<(OStream &os, const std::multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <class OStream, class T> OStream &operator<<(OStream &os, const std::unordered_multiset<T> &vec) { os << '{'; for (auto v : vec) os << v << ','; os << '}'; return os; }
template <class OStream, class T, class U> OStream &operator<<(OStream &os, const std::pair<T, U> &pa) { return os << '(' << pa.first << ',' << pa.second << ')'; }
template <class OStream, class TK, class TV> OStream &operator<<(OStream &os, const std::map<TK, TV> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
template <class OStream, class TK, class TV, class TH> OStream &operator<<(OStream &os, const std::unordered_map<TK, TV, TH> &mp) { os << '{'; for (auto v : mp) os << v.first << "=>" << v.second << ','; os << '}'; return os; }
#ifdef HITONANODE_LOCAL
const string COLOR_RESET = "\033[0m", BRIGHT_GREEN = "\033[1;32m", BRIGHT_RED = "\033[1;31m", BRIGHT_CYAN = "\033[1;36m", NORMAL_CROSSED = "\033[0;9;37m", RED_BACKGROUND = "\033[1;41m", NORMAL_FAINT = "\033[0;2m";
#define dbg(x) std::cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << std::endl
#define dbgif(cond, x) ((cond) ? std::cerr << BRIGHT_CYAN << #x << COLOR_RESET << " = " << (x) << NORMAL_FAINT << " (L" << __LINE__ << ") " << __FILE__ << COLOR_RESET << std::endl : std::cerr)
#else
#define dbg(x) ((void)0)
#define dbgif(cond, x) ((void)0)
#endif


uint32_t rand_int() // XorShift random integer generator
{
    static uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    uint32_t t = x ^ (x << 11);
    x = y;
    y = z;
    z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
double rand_double() { return (double)rand_int() / UINT32_MAX; }

#include <atcoder/modint>
#include <atcoder/convolution>
#include <atcoder/segtree>
#include <atcoder/string>

int op(int l, int r) { return std::min(l, r); }
int e() { return 1 << 29; }

string solve(const string &S1_, const string &S2) {
    const int N = S1_.size(), M = S2.size();
    string S1a = S1_;
    for (auto &c : S1a) {
        if (c == '?') c = 'a';
    }
    const auto z_algo = atcoder::z_algorithm(S2 + "_" + S1a);

    const auto sa = atcoder::suffix_array(S2 + "_" + S1a);
    vector<int> sainv(sa.size());
    REP(i, sa.size()) sainv.at(sa.at(i)) = i;

    const auto lcp = atcoder::lcp_array(S2 + "_" + S1a, sa);
    atcoder::segtree<int, op, e> lcptree(lcp);

    REP(_, 1000) rand_int();
    vector<atcoder::modint998244353> hash(26);
    for (auto &x : hash) x = rand_int();
    decltype(hash) f, g;
    for (auto c : S1_) {
        if (c == '?') {
            f.push_back(0);
        } else {
            f.push_back(hash.at(c - 'a'));
        }
    }

    auto f2 = f;
    for (auto &x : f2) x *= x;
    auto f3 = f2;
    REP(i, f3.size()) f3.at(i) *= f.at(i);

    for (auto c : S2) g.push_back(hash.at(c - 'a'));
    reverse(ALL(g));
    auto g2 = g;
    for (auto &x : g2) x *= x;
    decltype(g) g0(g.size(), 1);

    auto conv = atcoder::convolution(g0, f3), c2 = atcoder::convolution(g, f2), c3 = atcoder::convolution(g2, f);
    REP(i, conv.size()) conv.at(i) += c3.at(i) - c2.at(i) * 2;
    vector<int> heads;
    FOR(i, M - 1, N) if (conv.at(i) == 0) heads.push_back(i - (M - 1));

    if (heads.empty()) return "-1";

    // -1: same
    auto solve = [&](int l, int r) -> int {
        assert(l < r);
        if (r - l < M) {

            if (int z = z_algo.at(M + 1 + l); z < r - l) {
                auto lhs = S2.at(z), rhs = S1a.at(l + z);
                assert(lhs != rhs);
                return lhs < rhs;
            }

            if (int z = z_algo.at(r - l); z < M - (r - l)) {
                auto lhs = S2.at(r - l + z), rhs = S2.at(z);
                assert(lhs != rhs);
                return lhs < rhs;
            }

            int lcur = sainv.at(M + 1 + l + M), rcur = sainv.at(M - (r - l));
            int matchlen = lcptree.prod(min(lcur, rcur), max(lcur, rcur));
            if (matchlen >= r - l) return -1;
            auto lhs = S1a.at(l + M + matchlen), rhs = S2.at(M - (r - l) + matchlen);
            assert(lhs != rhs);

            return lhs < rhs;
        } else {
            int lcur = sainv.at(0), rcur = sainv.at(M + 1 + l);
            int match = lcptree.prod(min(lcur, rcur), max(lcur, rcur));
            if (match < M) {
                auto lhs = S2.at(match);
                auto rhs = S1a.at(l + match);
                assert(lhs != rhs);
                return lhs < rhs;
            }

            lcur = sainv.at(M + 1 + r), rcur = sainv.at(0);
            match = lcptree.prod(min(lcur, rcur), max(lcur, rcur));
            if (match < M) {
                auto lhs = S1a.at(r + match);
                auto rhs = S2.at(match);
                return lhs < rhs;
            }
            return -1;
        }
    };

    auto comp = [&](int l, int r) -> bool {
        if (l == r) return false;
        if (l < r) {
            auto ret = solve(l, r);
            if (ret < 0) return false;
            return ret;
        } else {
            auto ret = solve(r, l);
            if (ret < 0) return false;
            return ret ^ 1;
        }
    };

    const int h = *std::min_element(heads.begin(), heads.end(), comp);
    string ret = S1a.substr(0, h) + S2 + S1a.substr(h + M);
    return ret;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        int N, M;
        string S1, S2;
        cin >> N >> M >> S1 >> S2;
        cout << solve(S1, S2) << '\n';
    }
}
0