Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #define ssize(a) (int)(a).size()
- #define all(a) (a).begin(), (a).end()
- using namespace std;
- using ll = long long;
- const int max_len = 1e5 + 10;
- char text[max_len];
- int p[max_len];
- int np[max_len];
- int c[max_len];
- int nc[max_len];
- int cnt[max_len];
- int text_len = 0;
- const int max_queries = 15740785;
- char query_s[max_queries];
- int query_begin[max_queries];
- int prefix_len[max_queries];
- int query_len = 0;
- int queries_cnt = 0;
- void build_sa() {
- int n = text_len;
- iota(p, p + n, 0);
- sort(p, p + n, [&](int i, int j) {
- return text[i] < text[j];
- });
- c[p[0]] = 0;
- for (int i = 1; i < n; ++i) {
- c[p[i]] = c[p[i - 1]] + (text[p[i]] != text[p[i - 1]]);
- }
- for (int k = 1; c[p[n - 1]] < n - 1; k *= 2) {
- for (int i = 0; i < n; ++i) {
- np[i] = p[i] - k;
- if (np[i] < 0)
- np[i] += n;
- }
- memset(cnt, 0, sizeof cnt);
- for (int i = 0; i < n; ++i) {
- ++cnt[c[i]];
- }
- for (int i = 1; i < n; ++i) {
- cnt[i] += cnt[i - 1];
- }
- for (int i = n - 1; i >= 0; --i) {
- p[--cnt[c[np[i]]]] = np[i];
- }
- nc[p[0]] = 0;
- for (int i = 1; i < n; ++i) {
- nc[p[i]] = nc[p[i - 1]];
- if (c[p[i]] != c[p[i - 1]]) {
- ++nc[p[i]];
- } else {
- int x = p[i - 1] + k;
- if (x > n)
- x -= n;
- int y = p[i] + k;
- if (y > n)
- y -= n;
- if (c[x] != c[y])
- ++nc[p[i]];
- }
- }
- memcpy(c, nc, sizeof c);
- }
- }
- const int max_log = 18;
- int st[max_log][max_len];
- void build_st() {
- int n = text_len;
- int logn = __lg(n);
- for (int i = 0; i < n; ++i) {
- st[0][i] = p[i];
- }
- for (int k = 1; k <= logn; ++k) {
- for (int i = 0; i + (1 << k) <= n; ++i) {
- st[k][i] = min(st[k - 1][i], st[k - 1][i + (1 << (k - 1))]);
- }
- }
- }
- int get_min(int l, int r) {
- int k = __lg(r - l);
- return min(st[k][l], st[k][r - (1 << k)]);
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- freopen("nenokku.in", "r", stdin);
- {
- char t;
- string s;
- while (cin >> t >> s) {
- for (auto& c : s) {
- c = tolower(c);
- }
- if (t == 'A') {
- for (auto& c : s) {
- text[text_len++] = c;
- }
- } else {
- query_begin[queries_cnt] = query_len;
- prefix_len[queries_cnt] = text_len;
- ++queries_cnt;
- for (auto& c : s) {
- query_s[query_len++] = c;
- }
- }
- }
- }
- text[text_len++] = '#';
- build_sa();
- build_st();
- for (int i = 0; i < queries_cnt; ++i) {
- int end = (i == queries_cnt - 1 ? query_len : query_begin[i + 1]);
- string s(query_s + query_begin[i], query_s + end);
- int s_len = end - query_begin[i];
- int l, r;
- int low = 0;
- int high = text_len + 1;
- int low_lcp = 0;
- int high_lcp = 0;
- while (high - low > 1) {
- int mid = (low + high) >> 1;
- int k = min(low_lcp, high_lcp);
- int suf = p[mid];
- while (k < s_len && text[suf + k] == s[k])
- ++k;
- if (k == s_len || text[suf + k] > s[k])
- high = mid, high_lcp = k;
- else
- low = mid, low_lcp = k;
- }
- l = high;
- if (high_lcp < s_len) {
- cout << "NO\n";
- continue;
- }
- low = l - 1;
- high = text_len + 1;
- low_lcp = 0;
- high_lcp = 0;
- while (high - low > 1) {
- int mid = (low + high) >> 1;
- int k = min(low_lcp, high_lcp);
- int suf = p[mid];
- while (k < s_len && text[suf + k] == s[k])
- ++k;
- if (k < s_len && text[suf + k] > s[k])
- high = mid, high_lcp = k;
- else
- low = mid, low_lcp = k;
- }
- r = high;
- if (l == r) {
- cout << "NO\n";
- } else {
- int mn = get_min(l, r);
- if (mn + s_len - 1 < prefix_len[i]) {
- cout << "YES\n";
- } else {
- cout << "NO\n";
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement