#include #include #include using namespace std; struct Node { int count = 0; Node* children[26] = {nullptr}; Node* parent = nullptr; }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; if (!(cin >> N)) return 0; Node* root = new Node(); // Trie 木の構築 for (int i = 0; i < N; ++i) { string A; cin >> A; Node* curr = root; curr->count++; for (char c : A) { int idx = c - 'a'; if (!curr->children[idx]) { curr->children[idx] = new Node(); curr->children[idx]->parent = curr; } curr = curr->children[idx]; curr->count++; } } int Q; cin >> Q; Node* curr = root; int invalid_depth = 0; // 一致するノードが存在しなくなってからの文字数 while (Q--) { int type; cin >> type; if (type == 1) { char x; cin >> x; if (invalid_depth > 0) { // すでに一致しない状態なら深さのカウントだけ増やす(省略処理) invalid_depth++; } else { int idx = x - 'a'; if (curr && curr->children[idx]) { curr = curr->children[idx]; } else { // 遷移先がないため Trie の範囲外へ出る invalid_depth = 1; curr = nullptr; // ノード参照を破棄してしまう } } } else if (type == 2) { if (invalid_depth > 0) { invalid_depth--; // invalid_depth が 0 に戻っても、curr が nullptr のまま復元されない! } else { if (curr && curr->parent) { curr = curr->parent; } } } else if (type == 3) { if (invalid_depth > 0 || curr == nullptr) { cout << 0 << "\n"; } else { cout << curr->count << "\n"; } } } return 0; }