제출 #1311454

#제출 시각아이디문제언어결과실행 시간메모리
1311454forevpuritySelling RNA Strands (JOI16_selling_rna)C++20
100 / 100
337 ms210644 KiB
#include <bits/stdc++.h>
using namespace std;

// clang-format off
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
template<class T> bool chmin(T &a,T b){if(b<a){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,T b){if(a<b){a=b;return 1;}else return 0;}
// clang-format on

const string RNA = "AGCU";
map<char, int> to_val;
map<int, char> to_ch;

const int ALPHA = 4;

struct Trie {
  struct Node {
    int child[ALPHA];
    int count;
    int exist;
    int l, r;
    Node() {
      fill(child, child + ALPHA, -1);
      count = exist = 0;
      l = r = -1;
    }
    int& operator[](int c) { return child[c]; }
  };

  vector<Node> nodes;

  Trie() { nodes.emplace_back(); }

  void add(const string& s, int i) {
    int at = 0;
    for (char ch : s) {
      int c = to_val[ch];
      if (nodes[at][c] == -1) {
        nodes[at][c] = size(nodes);
        nodes.emplace_back();
      }
      at = nodes[at][c];
      nodes[at].count++;
      if (nodes[at].l == -1) nodes[at].l = nodes[at].r = i;
      else {
        chmin(nodes[at].l, i);
        chmax(nodes[at].r, i);
      }
    }
    nodes[at].exist++;
  }

  pii get_range(const string& s) {
    int at = 0;
    pii res = {-1, -1};
    for (char ch : s) {
      int c = to_val[ch];
      if (nodes[at][c] == -1) return res;
      at = nodes[at][c];
    }
    if (at != -1) res = {nodes[at].l, nodes[at].r};
    return res;
  }

  void dfs(int at, string& c_str, vector<string>& ve) {
    for (int i = 0; i < nodes[at].exist; i++) ve.pb(c_str);

    for (int i = 0; i < 4; i++) {
      if (int to = nodes[at][i]; to != -1) {
        c_str.push_back(to_ch[i]);
        dfs(to, c_str, ve);
        c_str.pop_back();
      }
    }
  }

  vector<string> sort_str() {
    vector<string> ve;
    string c_str = "";
    dfs(0, c_str, ve);
    return ve;
  }
};

struct RTrie {
  struct Node {
    int child[ALPHA];
    int count;
    int exist;
    vector<int> idx;
    Node() {
      fill(child, child + ALPHA, -1);
      count = exist = 0;
    }
    int& operator[](int c) { return child[c]; }
  };

  vector<Node> nodes;

  RTrie() { nodes.emplace_back(); }

  void add(const string& s, int i) {
    int at = 0;
    for (char ch : s) {
      int c = to_val[ch];
      if (nodes[at][c] == -1) {
        nodes[at][c] = size(nodes);
        nodes.emplace_back();
      }
      at = nodes[at][c];
      nodes[at].count++;
      nodes[at].idx.pb(i);
    }
    nodes[at].exist++;
  }

  int query(string& s, pii range) {
    int at = 0;
    int res = 0;
    for (char ch : s) {
      int c = to_val[ch];
      at = nodes[at][c];
      if (at == -1) return res;
    }

    vector ve(all(nodes[at].idx));

    int l = lower_bound(all(ve), range.fi) - ve.begin();
    int r = upper_bound(all(ve), range.se) - ve.begin();
    res = r - l;

    return res;
  }
};

int main() {
  cin.tie(0)->sync_with_stdio(0);

  // 古力娜扎

  for (int i = 0; i < 4; i++) to_val[RNA[i]] = i;
  for (int i = 0; i < 4; i++) to_ch[i] = RNA[i];

  int n, m;
  cin >> n >> m;

  Trie sort_tr;
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    sort_tr.add(s, 0);
  }

  vector<string> ve = sort_tr.sort_str();

  Trie tr;
  RTrie r_tr;

  for (int i = 0; i < n; i++) tr.add(ve[i], i);
  for (int i = 0; i < n; i++) {
    reverse(all(ve[i]));
    r_tr.add(ve[i], i);
  }

  for (int i = 0; i < m; i++) {
    string pr, su;
    cin >> pr >> su;
    pii range = tr.get_range(pr);
    reverse(all(su));
    int res = r_tr.query(su, range);
    cout << res << '\n';
  }

  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...