QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#240528#7686. The Phantom Menaceucup-team159#WA 430ms3820kbC++2310.6kb2023-11-05 16:11:192023-11-05 16:11:21

Judging History

你现在查看的是最新测评结果

  • [2024-10-08 14:11:03]
  • hack成功,自动添加数据
  • (/hack/941)
  • [2024-10-08 10:05:28]
  • hack成功,自动添加数据
  • (/hack/940)
  • [2024-10-07 19:51:15]
  • hack成功,自动添加数据
  • (/hack/938)
  • [2024-10-07 19:28:01]
  • hack成功,自动添加数据
  • (/hack/937)
  • [2024-10-07 17:16:32]
  • hack成功,自动添加数据
  • (/hack/936)
  • [2024-10-07 16:53:09]
  • hack成功,自动添加数据
  • (/hack/935)
  • [2024-10-07 16:22:17]
  • hack成功,自动添加数据
  • (/hack/934)
  • [2023-11-05 16:11:21]
  • 评测
  • 测评结果:WA
  • 用时:430ms
  • 内存:3820kb
  • [2023-11-05 16:11:19]
  • 提交

answer

// #pragma GCC target("avx,avx2")
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
	if(x<y){ x=y; return true; }
	return false;
}
template<class T,class U> bool chmin(T& x, U y){
	if(y<x){ x=y; return true; }
	return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
    return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
  return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ~ ";
	dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {";  \
	for(auto v: x) cerr << v << ","; cerr << "}" << endl;
const bool debug = true;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
const bool debug = false;
#endif

template<class D> D divFloor(D a, D b){
	return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
	return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}

template<class E> pair<bool,V<int>> eulerianTour(const VV<E>& G){
	int N = G.size();
	int s = -1;
	rep(i,N) if(!G[i].empty()) s = i;
	if(s == -1){
		return make_pair(true,V<int>());
	}
	int M = 0;
	rep(i,N) M += G[i].size();
	V<int> it(N);
	V<int> euler;
	auto dfs = [&](auto&& self, int v) -> void {
		while(it[v] != si(G[v])){
			auto e = G[v][it[v]];
			it[v]++;
			self(self,e.to);
			euler.eb(e.id);
		}
	};
	dfs(dfs,s);
	reverse(all(euler));
	if(si(euler) != M) return make_pair(false,V<int>());
	return make_pair(true,euler);
}

struct Edge{
	int to,id;
	Edge(int to_, int id_):to(to_),id(id_){}
};

namespace internal {
using i64 = long long;
using u64 = unsigned long long;
using u128 = __uint128_t;

template <int BASE_NUM = 2>
struct Hash : array<u64, BASE_NUM> {
  using array<u64, BASE_NUM>::operator[];
  static constexpr int n = BASE_NUM;

  Hash() : array<u64, BASE_NUM>() {}

  static constexpr u64 md = (1ull << 61) - 1;

  constexpr static Hash set(const i64 &a) {
    Hash res;
    fill(begin(res), end(res), cast(a));
    return res;
  }
  Hash &operator+=(const Hash &r) {
    for (int i = 0; i < n; i++)
      if (((*this)[i] += r[i]) >= md) (*this)[i] -= md;
    return *this;
  }
  Hash &operator+=(const i64 &r) {
    u64 s = cast(r);
    for (int i = 0; i < n; i++)
      if (((*this)[i] += s) >= md) (*this)[i] -= md;
    return *this;
  }
  Hash &operator-=(const Hash &r) {
    for (int i = 0; i < n; i++)
      if (((*this)[i] += md - r[i]) >= md) (*this)[i] -= md;
    return *this;
  }
  Hash &operator-=(const i64 &r) {
    u64 s = cast(r);
    for (int i = 0; i < n; i++)
      if (((*this)[i] += md - s) >= md) (*this)[i] -= md;
    return *this;
  }
  Hash &operator*=(const Hash &r) {
    for (int i = 0; i < n; i++) (*this)[i] = modmul((*this)[i], r[i]);
    return *this;
  }
  Hash &operator*=(const i64 &r) {
    u64 s = cast(r);
    for (int i = 0; i < n; i++) (*this)[i] = modmul((*this)[i], s);
    return *this;
  }

  Hash operator+(const Hash &r) { return Hash(*this) += r; }
  Hash operator+(const i64 &r) { return Hash(*this) += r; }
  Hash operator-(const Hash &r) { return Hash(*this) -= r; }
  Hash operator-(const i64 &r) { return Hash(*this) -= r; }
  Hash operator*(const Hash &r) { return Hash(*this) *= r; }
  Hash operator*(const i64 &r) { return Hash(*this) *= r; }
  Hash operator-() const {
    Hash res;
    for (int i = 0; i < n; i++) res[i] = (*this)[i] == 0 ? 0 : md - (*this)[i];
    return res;
  }
  friend Hash pfma(const Hash &a, const Hash &b, const Hash &c) {
    Hash res;
    for (int i = 0; i < n; i++) res[i] = modfma(a[i], b[i], c[i]);
    return res;
  }
  friend Hash pfma(const Hash &a, const Hash &b, const i64 &c) {
    Hash res;
    u64 s = cast(c);
    for (int i = 0; i < n; i++) res[i] = modfma(a[i], b[i], s);
    return res;
  }

  Hash pow(long long e) {
    Hash a{*this}, res{Hash::set(1)};
    for (; e; a *= a, e >>= 1) {
      if (e & 1) res *= a;
    }
    return res;
  }

  static Hash get_basis() {
    static auto rand_time =
        chrono::duration_cast<chrono::nanoseconds>(
            chrono::high_resolution_clock::now().time_since_epoch())
            .count();
    static mt19937_64 rng(rand_time);
    Hash h;
    for (int i = 0; i < n; i++) {
      while (isPrimitive(h[i] = rng() % (md - 1) + 1) == false)
        ;
    }
    return h;
  }

 private:
  static u64 modpow(u64 a, u64 b) {
    u64 r = 1;
    for (a %= md; b; a = modmul(a, a), b >>= 1) r = modmul(r, a);
    return r;
  }
  static bool isPrimitive(u64 x) {
    for (auto &d : vector<u64>{2, 3, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321})
      if (modpow(x, (md - 1) / d) <= 1) return false;
    return true;
  }
  static inline constexpr u64 cast(const long long &a) {
    return a < 0 ? a + md : a;
  }
  static inline constexpr u64 modmul(const u64 &a, const u64 &b) { 
    u128 d = u128(a) * b;
    u64 ret = (u64(d) & md) + u64(d >> 61);
    return ret >= md ? ret - md : ret;
  }
  static inline constexpr u64 modfma(const u64 &a, const u64 &b, const u64 &c) {
    u128 d = u128(a) * b + c;
    u64 ret = (d >> 61) + (u64(d) & md);
    return ret >= md ? ret - md : ret;
  }
};

}  // namespace internal
template <typename Str, int BASE_NUM = 2>
struct RollingHash {
  using Hash = internal::Hash<BASE_NUM>;
  Str data;
  vector<Hash> hs, pw;
  int s;
  static Hash basis;

  RollingHash(const Str &S = Str()) { build(S); }

  void build(const Str &S) {
    data = S;
    s = S.size();
    hs.resize(s + 1);
    pw.resize(s + 1);
    pw[0] = Hash::set(1);
    hs[0] = Hash::set(0);
    for (int i = 1; i <= s; i++) {
      pw[i] = pw[i - 1] * basis;
      hs[i] = pfma(hs[i - 1], basis, S[i - 1]);
    }
  }

  Hash get(int l, int r = -1) const {
    if (r == -1) r = s;
    return pfma(hs[l], -pw[r - l], hs[r]);
  }

  // T の hash を返す
  static Hash get_hash(const Str &T) {
    Hash ret = Hash::set(0);
    for (int i = 0; i < (int)T.size(); i++) ret = pfma(ret, basis, T[i]);
    return ret;
  }

  // a + b の hash を返す
  // 引数 : a, b, b の長さ
  static Hash unite(Hash a, Hash b, long long bsize) {
    return pfma(a, basis.pow(bsize), b);
  }

  int find(Str &T, int lower = 0) const {
    auto ths = get_hash(T);
    for (int i = lower; i <= s - (int)T.size(); i++)
      if (ths == get(i, i + (int)T.size())) return i;
    return -1;
  }

  static int lcp(const RollingHash &a, const RollingHash &b, int al, int bl) {
    int ok = 0, ng = min(a.size() - al, b.size() - bl) + 1;
    while (ok + 1 < ng) {
      int med = (ok + ng) / 2;
      (a.get(al, med + al) == b.get(bl, med + bl) ? ok : ng) = med;
    }
    return ok;
  }

  static int strcmp(const RollingHash &a, const RollingHash &b, int al, int bl,
                    int ar = -1, int br = -1) {
    if (ar == -1) ar = a.size();
    if (br == -1) br = b.size();
    int n = min<int>({lcp(a, b, al, bl), ar - al, br - bl});
    return al + n == ar                      ? bl + n == br ? 0 : -1
           : bl + n == br                    ? 1
           : a.data[al + n] < b.data[bl + n] ? -1
                                             : 1;
  }

  int size() const { return s; }
};

template <typename Str, int BASE_NUM>
typename RollingHash<Str, BASE_NUM>::Hash RollingHash<Str, BASE_NUM>::basis =
    internal::Hash<BASE_NUM>::get_basis();
using roriha = RollingHash<string, 2>;
using Hash = internal::Hash<2>;

void solve(){
	int N,M; cin >> N >> M;
	V<string> A(N),B(N);
	rep(i,N) cin >> A[i];
	rep(i,N) cin >> B[i];
	auto OUT = [&](V<int>& a, V<int>& b){
		if(debug){
			rep(i,N) cout << A[a[i]];
			cout << endl;
			rep(i,N) cout << B[b[i]];
			cout << endl;
		}
		rep(i,N) cout << a[i]+1 << " ";
		cout << '\n';
		rep(i,N) cout << b[i]+1 << " ";
		cout << '\n';
	};
	{
		// r = 0
		V<int> idxA(N),idxB(N);
		iota(all(idxA),0); iota(all(idxB),0);
		sort(all(idxA),[&](int l,int r){return A[l]<A[r];});
		sort(all(idxB),[&](int l,int r){return B[l]<B[r];});
		bool ok = true;
		rep(i,N) if(A[idxA[i]] != B[idxB[i]]) ok = false;
		if(ok){
			OUT(idxA,idxB);
			return;
		}
	}
	V<roriha> rhA(N),rhB(N);
	rep(i,N){
		rhA[i].build(A[i]);
		rhB[i].build(B[i]);
	}
	vector<Hash> hu,hd;
	vector<Hash> Al(N),Ar(N),Bl(N),Br(N);
	rep1(r,M-1){
		hu.clear(); hd.clear();
		rep(i,N){
			Al[i] = rhA[i].get(0,r);
			Ar[i] = rhA[i].get(r,M);
			Bl[i] = rhB[i].get(0,M-r);
			Br[i] = rhB[i].get(M-r,M);
			hu.pb(Al[i]); hu.pb(Br[i]);
			hd.pb(Ar[i]); hd.pb(Bl[i]);
		}
		mkuni(hu); mkuni(hd);
		int Hu = si(hu), Hd = si(hd);
		VV<Edge> G(Hu+Hd);
		show(Hu);show(Hd);
		rep(i,N){
			int al = lwb(hu,Al[i]);
			int ar = lwb(hd,Ar[i]);
			int bl = lwb(hd,Bl[i]);
			int br = lwb(hu,Br[i]);
			show(al);show(ar);show(bl);show(br);
			G[al].eb(Hu+ar,i);
			G[Hu+bl].eb(br,i+N);
		}
		auto waf = eulerianTour(G);
		if(waf.fs){
			auto es = waf.sc;
			if(es[0] >= N){
				rotate(es.begin(),es.begin()+1,es.end());
			}
			assert(es[0] < N);
			V<int> a(N),b(N);
			rep(i,N){
				a[i] = es[i+i], b[i] = es[i+i+1]-N;
			}
			OUT(a,b);
			return;
		}
	}
	cout << -1 << '\n';
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);		//DON'T USE scanf/printf/puts !!
	cout << fixed << setprecision(20);

	int T; cin >> T;
	while(T--) solve();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3708kb

input:

2
3 3
abc
ghi
def
bcd
efg
hia
1 3
abc
def

output:

1 3 2 
1 2 3 
-1

result:

ok 2 cases (2 test cases)

Test #2:

score: 0
Accepted
time: 413ms
memory: 3596kb

input:

1000000
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
b
b
1 1
a
b
1 1
b
a
1 1
a
a
1 1
...

output:

1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
...

result:

ok 1000000 cases (1000000 test cases)

Test #3:

score: -100
Wrong Answer
time: 430ms
memory: 3820kb

input:

500000
1 2
dd
ba
1 2
cd
ba
1 2
bd
ba
1 2
ad
ba
1 2
dc
ba
1 2
cc
ba
1 2
bc
ba
1 2
ac
ba
1 2
db
ba
1 2
cb
ba
1 2
bb
ba
1 2
ab
ba
1 2
da
ba
1 2
ca
ba
1 2
ba
ba
1 2
aa
ba
1 2
dd
aa
1 2
cd
aa
1 2
bd
aa
1 2
ad
aa
1 2
dc
aa
1 2
cc
aa
1 2
bc
aa
1 2
ac
aa
1 2
db
aa
1 2
cb
aa
1 2
bb
aa
1 2
ab
aa
1 2
da
aa
1 2...

output:

-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
1 
1 
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
1 
1 
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
-1
1 
1 
-1
1 
1 
-1
-1
-1
1 
1 
-1
-1
-1
1 
1 
...

result:

wrong answer not cyclic isomorphism (test case 4)