Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("03")
- #define _CRT_SECURE_NO_WARNINGS
- #include "bits/stdc++.h"
- using namespace std;
- using namespace chrono;
- #define all(a) a.begin(), a.end()
- #define allr(a) a.rbegin(), a.rend()
- #define endl "\n"
- #define fast_io ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
- mt19937 rnd(std::chrono::high_resolution_clock::now().time_since_epoch().count());
- typedef long long ll;
- typedef long double ld;
- static struct FastInput {
- static constexpr int BUF_SIZE = 1 << 20;
- char buf[BUF_SIZE];
- size_t chars_read = 0;
- size_t buf_pos = 0;
- FILE* in = stdin;
- char cur = 0;
- inline char get_char() {
- if (buf_pos >= chars_read) {
- chars_read = fread(buf, 1, BUF_SIZE, in);
- buf_pos = 0;
- buf[0] = (chars_read == 0 ? -1 : buf[0]);
- }
- return cur = buf[buf_pos++];
- }
- inline void tie(int) {}
- inline explicit operator bool() {
- return cur != -1;
- }
- inline static bool is_blank(char c) {
- return c <= ' ';
- }
- inline bool skip_blanks() {
- while (is_blank(cur) && cur != -1) {
- get_char();
- }
- return cur != -1;
- }
- inline FastInput& operator>>(char& c) {
- skip_blanks();
- c = cur;
- return *this;
- }
- inline FastInput& operator>>(string& s) {
- if (skip_blanks()) {
- s.clear();
- do {
- s += cur;
- } while (!is_blank(get_char()));
- }
- return *this;
- }
- template <typename T>
- inline FastInput& read_integer(T& n) {
- n = 0;
- if (skip_blanks()) {
- int sign = +1;
- if (cur == '-') {
- sign = -1;
- get_char();
- }
- do {
- n += n + (n << 3) + cur - '0';
- } while (!is_blank(get_char()));
- n *= sign;
- }
- return *this;
- }
- template <typename T>
- inline typename enable_if<is_integral<T>::value, FastInput&>::type operator>>(T& n) {
- return read_integer(n);
- }
- #if !defined(_WIN32) || defined(_WIN64)
- inline FastInput& operator>>(__int128& n) {
- return read_integer(n);
- }
- #endif
- template <typename T>
- inline typename enable_if<is_floating_point<T>::value, FastInput&>::type operator>>(T& n) {
- // not sure if really fast, for compatibility only
- n = 0;
- if (skip_blanks()) {
- string s;
- (*this) >> s;
- sscanf(s.c_str(), "%lf", &n);
- }
- return *this;
- }
- } fast_input;
- static struct FastOutput {
- static constexpr int BUF_SIZE = 1 << 20;
- char buf[BUF_SIZE];
- size_t buf_pos = 0;
- static constexpr int TMP_SIZE = 1 << 20;
- char tmp[TMP_SIZE];
- FILE* out = stdout;
- inline void put_char(char c) {
- buf[buf_pos++] = c;
- if (buf_pos == BUF_SIZE) {
- fwrite(buf, 1, buf_pos, out);
- buf_pos = 0;
- }
- }
- ~FastOutput() {
- fwrite(buf, 1, buf_pos, out);
- }
- inline FastOutput& operator<<(char c) {
- put_char(c);
- return *this;
- }
- inline FastOutput& operator<<(const char* s) {
- while (*s) {
- put_char(*s++);
- }
- return *this;
- }
- inline FastOutput& operator<<(const string& s) {
- for (int i = 0; i < (int)s.size(); i++) {
- put_char(s[i]);
- }
- return *this;
- }
- template <typename T>
- inline char* integer_to_string(T n) {
- // beware of TMP_SIZE
- char* p = tmp + TMP_SIZE - 1;
- if (n == 0) {
- *--p = '0';
- }
- else {
- bool is_negative = false;
- if (n < 0) {
- is_negative = true;
- n = -n;
- }
- while (n > 0) {
- *--p = (char)('0' + n % 10);
- n /= 10;
- }
- if (is_negative) {
- *--p = '-';
- }
- }
- return p;
- }
- template <typename T>
- inline typename enable_if<is_integral<T>::value, char*>::type stringify(T n) {
- return integer_to_string(n);
- }
- #if !defined(_WIN32) || defined(_WIN64)
- inline char* stringify(__int128 n) {
- return integer_to_string(n);
- }
- #endif
- template <typename T>
- inline typename enable_if<is_floating_point<T>::value, char*>::type stringify(T n) {
- sprintf(tmp, "%.17f", n);
- return tmp;
- }
- template <typename T>
- inline FastOutput& operator<<(const T& n) {
- auto p = stringify(n);
- for (; *p != 0; p++) {
- put_char(*p);
- }
- return *this;
- }
- } fast_output;
- #define cin fast_input
- #define cout fast_output
- string p;
- struct Node {
- ll go[26], cur = 0, terminal = 0, binup[21], dp = 0, prefix[27], siz = 0, down[26];
- };
- vector<Node> trie(1);
- void add(string& s) {
- ll cur_v = 0;
- for (ll i = 0; i < (ll)s.size(); i++) {
- char level = s[i] - 'a';
- if (trie[cur_v].go[level] == 0) {
- trie.push_back(Node());
- trie[cur_v].go[level] = (ll)trie.size() - 1;
- trie[trie[cur_v].go[level]].cur = trie[cur_v].cur + 1;
- }
- cur_v = trie[cur_v].go[level];
- }
- trie[cur_v].terminal++;
- return;
- }
- void dfs(ll v = 0, ll p = 0) {
- trie[v].binup[0] = p;
- for (ll i = 0; i + 1 < 21; i++)
- trie[v].binup[i + 1] = trie[trie[v].binup[i]].binup[i];\
- trie[v].dp += trie[p].dp + trie[v].terminal;
- trie[v].siz = trie[v].terminal;
- ll now_sum = 0;
- trie[v].prefix[0] = 0;
- for (ll c = 0; c < 26; c++) {
- if (trie[v].go[c] != 0) {
- trie[trie[v].go[c]].dp += now_sum;
- dfs(trie[v].go[c], v);
- trie[v].siz += trie[trie[v].go[c]].siz;
- trie[v].down[c] = trie[trie[v].go[c]].down[c];
- now_sum += trie[trie[v].go[c]].siz;
- }
- else {
- trie[v].down[c] = v;
- }
- trie[v].prefix[c + 1] = now_sum;
- }
- }
- ll cur_v = 0, lvl = -1;
- ll get() {
- ll ans = trie[cur_v].dp;
- if ((ll)p.size() == trie[cur_v].cur) {
- ans -= trie[cur_v].terminal;
- }
- else {
- for (ll i = 0; i < lvl; i++) {
- if (trie[cur_v].go[i] != 0) {
- ans += trie[trie[cur_v].go[i]].siz;
- }
- }
- }
- return ans;
- }
- void need(ll c) {
- cur_v = trie[cur_v].down[c];
- ll to = max(trie[cur_v].cur-(ll)p.size(), (ll)0);
- for (ll i = 20; i >= 0; --i) {
- if (to >> i & 1) {
- cur_v = trie[cur_v].binup[i];
- }
- }
- if (trie[cur_v].cur == (ll)p.size())
- lvl = -1;
- else
- lvl = c;
- }
- signed main() {
- #ifdef _DEBUG
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- srand(time(NULL));
- ll n;
- cin >> n;
- ll q;
- cin >> q;
- cin >> p;
- for (ll i = 0; i < n; i++) {
- string s;
- cin >> s;
- add(s);
- }
- dfs();
- for (ll i = 0; i < (ll)p.size(); i++) {
- ll level = p[i] - 'a';
- if (trie[cur_v].go[level] == 0) {
- lvl = level;
- break;
- }
- cur_v = trie[cur_v].go[level];
- }
- cout << get() << endl;
- while (q--) {
- ll pos;
- char in;
- cin >> pos >> in;
- --pos;
- ll c = in - 'a';
- if (pos > trie[cur_v].cur) {
- }
- else {
- ll to = trie[cur_v].cur - pos;
- for (ll i = 20; i >= 0; --i) {
- if (to >> i & 1) {
- cur_v = trie[cur_v].binup[i];
- }
- }
- need(c);
- }
- cout << get() << endl;;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement