Submission #342880

#TimeUsernameProblemLanguageResultExecution timeMemory
342880KoDSelling RNA Strands (JOI16_selling_rna)C++17
100 / 100
365 ms169544 KiB
#line 1 "main.cpp"

/**
 * @title Template
 */

#include <iostream>
#include <algorithm>
#include <utility>
#include <numeric>
#include <vector>
#include <array>
#include <cassert>

#line 2 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"

#line 4 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"

class range {
  struct iter {
    std::size_t itr;
    constexpr iter(std::size_t pos) noexcept: itr(pos) { }
    constexpr void operator ++ () noexcept { ++itr; }
    constexpr bool operator != (iter other) const noexcept { return itr != other.itr; }
    constexpr std::size_t operator * () const noexcept { return itr; }
  };

  struct reviter {
    std::size_t itr;
    constexpr reviter(std::size_t pos) noexcept: itr(pos) { }
    constexpr void operator ++ () noexcept { --itr; }
    constexpr bool operator != (reviter other) const noexcept { return itr != other.itr; }
    constexpr std::size_t operator * () const noexcept { return itr; }
  };

  const iter first, last;

public:
  constexpr range(std::size_t first, std::size_t last) noexcept: first(first), last(std::max(first, last)) { }
  constexpr iter begin() const noexcept { return first; }
  constexpr iter end() const noexcept { return last; }
  constexpr reviter rbegin() const noexcept { return reviter(*last - 1); } 
  constexpr reviter rend() const noexcept { return reviter(*first - 1); } 
};

/**
 * @title Range
 */
#line 15 "main.cpp"

using i32 = std::int32_t;
using i64 = std::int64_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

constexpr i32 inf32 = (u32) ~0 >> 2;
constexpr i64 inf64 = (u64) ~0 >> 2;

template <class T>
using Vec = std::vector<T>;

constexpr usize match(const char c) {
  if (c == 'A') return 0;
  if (c == 'G') return 1;
  if (c == 'C') return 2;
  if (c == 'U') return 3;
  return 4;
}

struct Node {
  std::array<usize, 4> next{};
  Vec<usize> idx;
};

usize next(Vec<Node> &trie, const usize u, const usize k) {
  if (trie[u].next[k] == 0) {
    const auto n = trie.size();
    trie.push_back(Node {});
    trie[u].next[k] = n;
  }
  return trie[u].next[k];
}

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);
  usize N, M;
  std::cin >> N >> M;
  Vec<std::string> S(N);
  for (auto &x: S) {
    std::cin >> x;
    std::reverse(x.begin(), x.end());
  }
  std::sort(S.begin(), S.end());
  Vec<Node> front;
  front.push_back(Node {});
  for (auto i: range(0, N)) {
    usize pf = 0;
    for (auto j: range(0, S[i].size())) {
      pf = next(front, pf, match(S[i][S[i].size() - j - 1]));
      front[pf].idx.push_back(i);
    }
  }
  while (M--) {
    std::string P, Q;
    std::cin >> P >> Q;
    usize pf = 0;
    for (auto i: range(0, P.size())) {
      pf = next(front, pf, match(P[i]));
    }
    if (front[pf].idx.empty()) {
      std::cout << 0 << '\n';
      continue;
    }
    std::reverse(Q.begin(), Q.end());
    const auto low = [&]() -> usize {
      if (S[front[pf].idx.front()] >= Q) {
        return 0;
      }
      usize ok = front[pf].idx.size(), ng = 0;
      while (ok - ng > 1) {
        const auto md = (ok + ng) / 2;
        if (S[front[pf].idx[md]] >= Q) {
          ok = md;
        }
        else {
          ng = md;
        }
      }
      return ok;
    }();
    const auto high = [&]() -> usize {
      if (S[front[pf].idx.front()].substr(0, Q.size()) > Q) {
        return 0;
      }
      usize ok = front[pf].idx.size(), ng = 0;
      while (ok - ng > 1) {
        const auto md = (ok + ng) / 2;
        if (S[front[pf].idx[md]].substr(0, Q.size()) > Q) {
          ok = md;
        }
        else {
          ng = md;
        }
      }
      return ok;
    }();
    std::cout << high - low << '\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...