結果
問題 | No.2231 Surprising Flash! |
ユーザー |
![]() |
提出日時 | 2023-02-24 22:29:34 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 960 ms / 4,000 ms |
コード長 | 17,435 bytes |
コンパイル時間 | 3,698 ms |
コンパイル使用メモリ | 190,580 KB |
最終ジャッジ日時 | 2025-02-10 21:35:53 |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 44 |
ソースコード
#pragma GCC optimize("O3")#pragma GCC optimize("unroll-loops")#include<iostream>#include<string>#include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<functional>#include<iomanip>#include<queue>#include<ciso646>#include<random>#include<map>#include<set>#include<bitset>#include<stack>#include<unordered_map>#include<unordered_set>#include<utility>#include<cassert>#include<complex>#include<numeric>#include<array>#include<chrono>using namespace std;//#define int long longtypedef long long ll;typedef unsigned long long ul;typedef unsigned int ui;//ll mod = 1;constexpr ll mod = 998244353;//constexpr ll mod = 1000000007;const ll INF = mod * mod;typedef pair<int, int>P;#define rep(i,n) for(int i=0;i<n;i++)#define per(i,n) for(int i=n-1;i>=0;i--)#define Rep(i,sta,n) for(int i=sta;i<n;i++)#define rep1(i,n) for(int i=1;i<=n;i++)#define per1(i,n) for(int i=n;i>=1;i--)#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)#define all(v) (v).begin(),(v).end()typedef pair<ll, ll> LP;template<typename T>void chmin(T& a, T b) {a = min(a, b);}template<typename T>void chmax(T& a, T b) {a = max(a, b);}template<typename T>vector<T> vmerge(vector<T>& a, vector<T>& b) {vector<T> res;int ida = 0, idb = 0;while (ida < a.size() || idb < b.size()) {if (idb == b.size()) {res.push_back(a[ida]); ida++;}else if (ida == a.size()) {res.push_back(b[idb]); idb++;}else {if (a[ida] < b[idb]) {res.push_back(a[ida]); ida++;}else {res.push_back(b[idb]); idb++;}}}return res;}template<typename T>void cinarray(vector<T>& v) {rep(i, v.size())cin >> v[i];}template<typename T>void coutarray(vector<T>& v) {rep(i, v.size()) {if (i > 0)cout << " "; cout << v[i];}cout << "\n";}ll mod_pow(ll x, ll n, ll m = mod) {if (n < 0) {ll res = mod_pow(x, -n, m);return mod_pow(res, m - 2, m);}if (abs(x) >= m)x %= m;if (x < 0)x += m;//if (x == 0)return 0;ll res = 1;while (n) {if (n & 1)res = res * x % m;x = x * x % m; n >>= 1;}return res;}//mod should be <2^31struct modint {int n;modint() :n(0) { ; }modint(ll m) {if (m < 0 || mod <= m) {m %= mod; if (m < 0)m += mod;}n = m;}operator int() { return n; }};bool operator==(modint a, modint b) { return a.n == b.n; }bool operator<(modint a, modint b) { return a.n < b.n; }modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= (int)mod; return a; }modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += (int)mod; return a; }modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }modint operator+(modint a, modint b) { return a += b; }modint operator-(modint a, modint b) { return a -= b; }modint operator*(modint a, modint b) { return a *= b; }modint operator^(modint a, ll n) {if (n == 0)return modint(1);modint res = (a * a) ^ (n / 2);if (n % 2)res = res * a;return res;}ll inv(ll a, ll p) {return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);}modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }modint operator/=(modint& a, modint b) { a = a / b; return a; }const int max_n = 1 << 20;modint fact[max_n], factinv[max_n];void init_f() {fact[0] = modint(1);for (int i = 0; i < max_n - 1; i++) {fact[i + 1] = fact[i] * modint(i + 1);}factinv[max_n - 1] = modint(1) / fact[max_n - 1];for (int i = max_n - 2; i >= 0; i--) {factinv[i] = factinv[i + 1] * modint(i + 1);}}modint comb(int a, int b) {if (a < 0 || b < 0 || a < b)return 0;return fact[a] * factinv[b] * factinv[a - b];}modint combP(int a, int b) {if (a < 0 || b < 0 || a < b)return 0;return fact[a] * factinv[a - b];}ll gcd(ll a, ll b) {a = abs(a); b = abs(b);if (a < b)swap(a, b);while (b) {ll r = a % b; a = b; b = r;}return a;}using ld = long double;//typedef long double ld;typedef pair<ld, ld> LDP;const ld eps = 1e-6;const ld pi = acosl(-1.0);template<typename T>void addv(vector<T>& v, int loc, T val) {if (loc >= v.size())v.resize(loc + 1, 0);v[loc] += val;}/*const int mn = 2000005;bool isp[mn];vector<int> ps;void init() {fill(isp + 2, isp + mn, true);for (int i = 2; i < mn; i++) {if (!isp[i])continue;ps.push_back(i);for (int j = 2 * i; j < mn; j += i) {isp[j] = false;}}}*///[,val)template<typename T>auto prev_itr(set<T>& st, T val) {auto res = st.lower_bound(val);if (res == st.begin())return st.end();res--; return res;}//[val,)template<typename T>auto next_itr(set<T>& st, T val) {auto res = st.lower_bound(val);return res;}using mP = pair<modint, modint>;mP operator+(mP a, mP b) {return { a.first + b.first,a.second + b.second };}mP operator+=(mP& a, mP b) {a = a + b; return a;}mP operator-(mP a, mP b) {return { a.first - b.first,a.second - b.second };}mP operator-=(mP& a, mP b) {a = a - b; return a;}LP operator+(LP a, LP b) {return { a.first + b.first,a.second + b.second };}LP operator+=(LP& a, LP b) {a = a + b; return a;}LP operator-(LP a, LP b) {return { a.first - b.first,a.second - b.second };}LP operator-=(LP& a, LP b) {a = a - b; return a;}mt19937 mt(time(0));const string drul = "DRUL";string senw = "SENW";//DRUL,or SENWint dx[4] = { 1,0,-1,0 };int dy[4] = { 0,1,0,-1 };//-----------------------------------------//https://github.com/atcoder/ac-librarynamespace internal {std::vector<int> sa_naive(const std::vector<int>& s) {int n = int(s.size());std::vector<int> sa(n);std::iota(sa.begin(), sa.end(), 0);std::sort(sa.begin(), sa.end(), [&](int l, int r) {if (l == r) return false;while (l < n && r < n) {if (s[l] != s[r]) return s[l] < s[r];l++;r++;}return l == n;});return sa;}std::vector<int> sa_doubling(const std::vector<int>& s) {int n = int(s.size());std::vector<int> sa(n), rnk = s, tmp(n);std::iota(sa.begin(), sa.end(), 0);for (int k = 1; k < n; k *= 2) {auto cmp = [&](int x, int y) {if (rnk[x] != rnk[y]) return rnk[x] < rnk[y];int rx = x + k < n ? rnk[x + k] : -1;int ry = y + k < n ? rnk[y + k] : -1;return rx < ry;};std::sort(sa.begin(), sa.end(), cmp);tmp[sa[0]] = 0;for (int i = 1; i < n; i++) {tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);}std::swap(tmp, rnk);}return sa;}// SA-IS, linear-time suffix array construction// Reference:// G. Nong, S. Zhang, and W. H. Chan,// Two Efficient Algorithms for Linear Time Suffix Array Constructiontemplate <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>std::vector<int> sa_is(const std::vector<int>& s, int upper) {int n = int(s.size());if (n == 0) return {};if (n == 1) return { 0 };if (n == 2) {if (s[0] < s[1]) {return { 0, 1 };}else {return { 1, 0 };}}if (n < THRESHOLD_NAIVE) {return sa_naive(s);}if (n < THRESHOLD_DOUBLING) {return sa_doubling(s);}std::vector<int> sa(n);std::vector<bool> ls(n);for (int i = n - 2; i >= 0; i--) {ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);}std::vector<int> sum_l(upper + 1), sum_s(upper + 1);for (int i = 0; i < n; i++) {if (!ls[i]) {sum_s[s[i]]++;}else {sum_l[s[i] + 1]++;}}for (int i = 0; i <= upper; i++) {sum_s[i] += sum_l[i];if (i < upper) sum_l[i + 1] += sum_s[i];}auto induce = [&](const std::vector<int>& lms) {std::fill(sa.begin(), sa.end(), -1);std::vector<int> buf(upper + 1);std::copy(sum_s.begin(), sum_s.end(), buf.begin());for (auto d : lms) {if (d == n) continue;sa[buf[s[d]]++] = d;}std::copy(sum_l.begin(), sum_l.end(), buf.begin());sa[buf[s[n - 1]]++] = n - 1;for (int i = 0; i < n; i++) {int v = sa[i];if (v >= 1 && !ls[v - 1]) {sa[buf[s[v - 1]]++] = v - 1;}}std::copy(sum_l.begin(), sum_l.end(), buf.begin());for (int i = n - 1; i >= 0; i--) {int v = sa[i];if (v >= 1 && ls[v - 1]) {sa[--buf[s[v - 1] + 1]] = v - 1;}}};std::vector<int> lms_map(n + 1, -1);int m = 0;for (int i = 1; i < n; i++) {if (!ls[i - 1] && ls[i]) {lms_map[i] = m++;}}std::vector<int> lms;lms.reserve(m);for (int i = 1; i < n; i++) {if (!ls[i - 1] && ls[i]) {lms.push_back(i);}}induce(lms);if (m) {std::vector<int> sorted_lms;sorted_lms.reserve(m);for (int v : sa) {if (lms_map[v] != -1) sorted_lms.push_back(v);}std::vector<int> rec_s(m);int rec_upper = 0;rec_s[lms_map[sorted_lms[0]]] = 0;for (int i = 1; i < m; i++) {int l = sorted_lms[i - 1], r = sorted_lms[i];int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;bool same = true;if (end_l - l != end_r - r) {same = false;}else {while (l < end_l) {if (s[l] != s[r]) {break;}l++;r++;}if (l == n || s[l] != s[r]) same = false;}if (!same) rec_upper++;rec_s[lms_map[sorted_lms[i]]] = rec_upper;}auto rec_sa =sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);for (int i = 0; i < m; i++) {sorted_lms[i] = lms[rec_sa[i]];}induce(sorted_lms);}return sa;}} // namespace internalstd::vector<int> suffix_array(const std::vector<int>& s, int upper) {assert(0 <= upper);for (int d : s) {assert(0 <= d && d <= upper);}auto sa = internal::sa_is(s, upper);return sa;}template <class T> std::vector<int> suffix_array(const std::vector<T>& s) {int n = int(s.size());std::vector<int> idx(n);iota(idx.begin(), idx.end(), 0);sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });std::vector<int> s2(n);int now = 0;for (int i = 0; i < n; i++) {if (i && s[idx[i - 1]] != s[idx[i]]) now++;s2[idx[i]] = now;}return internal::sa_is(s2, now);}std::vector<int> suffix_array(const std::string& s) {int n = int(s.size());std::vector<int> s2(n);for (int i = 0; i < n; i++) {s2[i] = s[i];}return internal::sa_is(s2, 255);}// Reference:// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its// Applicationstemplate <class T>std::vector<int> lcp_array(const std::vector<T>& s,const std::vector<int>& sa) {int n = int(s.size());assert(n >= 1);std::vector<int> rnk(n);for (int i = 0; i < n; i++) {rnk[sa[i]] = i;}std::vector<int> lcp(n - 1);int h = 0;for (int i = 0; i < n; i++) {if (h > 0) h--;if (rnk[i] == 0) continue;int j = sa[rnk[i] - 1];for (; j + h < n && i + h < n; h++) {if (s[j + h] != s[i + h]) break;}lcp[rnk[i] - 1] = h;}return lcp;}std::vector<int> lcp_array(const std::string& s, const std::vector<int>& sa) {int n = int(s.size());std::vector<int> s2(n);for (int i = 0; i < n; i++) {s2[i] = s[i];}return lcp_array(s2, sa);}struct sparse_table {private:int n;int tmp;vector<int> ori;vector<int> transtmp;vector<vector<int>> nodel;public:sparse_table(vector<int> _ori) {ori = _ori;n = ori.size();int cop = n;tmp = 0;while (cop > 0) {tmp++; cop >>= 1;}nodel.resize(tmp);rep(i, tmp)nodel[i].resize(n);rep(i, n) {nodel[0][i] = ori[i];}rep(j, tmp - 1) {rep(i, n) {if (i + (1 << j) < n) {nodel[j + 1][i] = min(nodel[j][i], nodel[j][i + (1 << j)]);}}}transtmp.resize(n + 1);int x = 1;int cnt = 0;rep1(i, n) {while (x * 2 <= i) {x *= 2; cnt++;}transtmp[i] = cnt;}}//[l,r)int query(int l, int r) {if (r - l == 0)return mod;int cnt = transtmp[r - l];return min(nodel[cnt][l], nodel[cnt][r - (1 << cnt)]);}};LDP operator*(const LDP& a, const LDP& b) {return LDP{ a.first * b.first - a.second * b.second , a.first * b.second + a.second * b.first };}LDP operator+(const LDP& a, const LDP& b) {return LDP{ a.first + b.first,a.second + b.second };}LDP operator-(const LDP& a, const LDP& b) {return LDP{ a.first - b.first,a.second - b.second };}//非再帰//eps=0.01を忘れずにtypedef vector<LDP> poly;poly dft(poly f, bool inverse = false) {int n = f.size(); int i, j, k;//bit左右反転for (i = 0, j = 1; j < n - 1; j++) {for (k = n >> 1; k > (i ^= k); k >>= 1);if (i > j)swap(f[i], f[j]);}for (int m = 2; m <= n; m *= 2) {LDP zeta = { cos(2 * pi / (ld)m), sin(2 * pi / (ld)m) };if (inverse) {zeta = { cos(2 * pi * (m - 1) / (ld)m), sin(2 * pi * (m - 1) / (ld)m) };}for (i = 0; i < n; i += m) {LDP powzeta = { 1,0 };for (k = i; k < i + m / 2; k++) {LDP t1 = f[k], t2 = powzeta * f[k + m / 2];f[k] = t1 + t2; f[k + m / 2] = t1 - t2;powzeta = powzeta * zeta;}}}if (inverse) {for (i = 0; i < n; i++) {f[i].first /= (ld)n;f[i].second /= (ld)n;}}return f;}poly multiply(poly g, poly h) {int n = 1; int sz = g.size() + h.size();while (n <= sz)n *= 2;while (g.size() < n) {g.push_back({ 0,0 });}while (h.size() < n) {h.push_back({ 0,0 });}poly gg = dft(g);poly hh = dft(h);poly ff;rep(i, n) {ff.push_back(gg[i] * hh[i]);}return dft(ff, true);}void solve() {int n, m; cin >> n >> m;string s, t; cin >> s >> t;poly fs(n);rep(i, n) {if (s[i] == '?')fs[i] = { 0,0 };else {int c = s[i] - 'a';ld t = (c + 1) * 2 * pi /(ld) 54;fs[i] = { cos(t),sin(t) };}}string rt = t;reverse(all(rt));poly ft(m);rep(i, m) {int c = rt[i] - 'a';ld t = -(c + 1) * 2 * pi / (ld) 54;ft[i] = { cos(t),sin(t) };}poly f = multiply(fs, ft);vector<int> ids;vector<int> cnt(n + 1);rep(i, n) {cnt[i + 1] = cnt[i];if (s[i] != '?')cnt[i + 1]++;}rep(i, n - m + 1) {ld val = 0;if (i+m-1 < f.size())val = f[i+m-1].first;int c = cnt[i + m] - cnt[i];//cout << f[i].first<<" "<<f[i].second << " " << c << "\n";if (abs(val - c) < eps) {ids.push_back(i);}}if (ids.empty()) {cout << -1 << "\n"; return;}string ns = s;rep(i, ns.size())if (ns[i] == '?')ns[i] = 'a';string al = ns + t;vector<int> sa = suffix_array(al);vector<int> rev(al.size());rep(i, sa.size())rev[sa[i]] = i;vector<int> lcp = lcp_array(al, sa);sparse_table st(lcp);auto query = [&](int i, int j) {i = rev[i];j = rev[j];if (i > j)swap(i, j);return st.query(i, j);};int adt = s.size();auto comp = [&](int i, int j) {if (i > j)swap(i, j);if (j - i >= m) {int cc = query(adt, i);if (cc < m) {assert(t[cc] != ns[i + cc]);if (t[cc] < ns[i + cc])return i;else return j;}cc = query(j, adt);if (cc < m) {assert(t[cc] != ns[j + cc]);if (t[cc] < ns[j + cc])return j;else return i;}//samereturn i;}else {int dif = j - i;int cc = query(adt, i);if (cc < dif) {assert(t[cc] != ns[i + cc]);if (t[cc] < ns[i + cc])return i;else return j;}cc = query(adt + dif, adt);if (cc < m - dif) {assert(t[cc] != t[cc + dif]);if (t[cc] < t[cc + dif])return j;else return i;}dif = m - dif;cc = query(i + m, adt + dif);if (cc < m - dif) {assert(t[cc + dif] != ns[i + m + cc]);if (t[cc + dif] < ns[i + m + cc])return j;else return i;}//samereturn i;}};int ci = ids[0];for (int i = 1; i < ids.size(); i++) {ci = comp(ci, ids[i]);}string ans = s;rep(j, m) {ans[ci + j] = t[j];}rep(i, n)if (ans[i] == '?')ans[i] = 'a';cout << ans << "\n";}signed main() {ios::sync_with_stdio(false);cin.tie(0);//cout << fixed << setprecision(10);//init_f();//init();//while(true)//expr();int t; cin >> t; rep(i, t)solve();return 0;}