Problem:
G： 検閲により置換 (Censored String)
Problem Statement
You are given the string
S
, and the set of strings
\mathcal P
whose size is
N
. Now we consider applying the following operation to
S
:
Choose exactly one character in
S
, and replace it with '*'.
Let
s_i
be a
i
-th character of
S
,
S_{ij}
be a consecutive substring in
S
such that
S = s_i s_{i+1}
$\cdots$
s_j
, and
p_k
as the
k
-th string of
P
. Your task is to calculate the minimum number of operations for satisfying the following condition.
For all pairs (
S_{ij}
,
p_k
), it is satisfied that
S_{ij} \neq p_k
.
Input
An input is given in the following format.
S
N
p_1
p_2
$\vdots$
p_N
In line
1
, you are given the string
S
.
In line
2
, given an integer
N
.
N
means the size of
P
.
From line
3
to the end, given
p_i
, the
i
-th string of
P
.
Constraints
1 \leq |S| \leq 10^5
1 \leq N \leq 10^5
1 \leq |p_1| + |p_2| +
$\cdots$
+ |p_N| \leq 10^5
If
i \neq j
, it is guaranteed that
p_i \neq p_j
S
, and
p_i
include lowercase letters only
Output
Print the minimum number of operations in one line.
Sample Input 1
brainfuck
1
fuck
Sample Output 1
1
For example, if you change "brainfuck" into "brainf*ck", you can satisfy the condition. You have to perform operation at least once, and it is the minimum value.
Sample Input 2
aaa
1
a
Sample Output 2
3
You have to operate for all characters.
Sample Input 3
hellshakeyano
3
hell
shake
key
Sample Output 3
2
In this case, for example, if you change "hellshakeyano" into "h*llsha*eyano", you can satisfy the condition. Notice if you replace one character, it might happen that several strings in the set
P
, which appear as the consecutive substring of
S
, simultaneously disappear.

Submitted solutions:

code_snippet: #line 1 "a.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2873"
#line 2 "string/Trie_Tree.hpp"
#include <vector>
#include <array>
#include <string>

namespace po167{
template<const int char_size,int base>
struct Trie_Tree
{
    struct Node{
        std::array<int, char_size> next_node;
        std::vector<int> terminate_node;
        int parent_node;
        int char_number;
        int accepet_count;
        explicit Node(int c_):parent_node(-1),char_number(c_),accepet_count(0){
            for(int i=0;i<char_size;i++) next_node[i]=-1;
        }
    };
    std::vector<Node> nodes;
    std::vector<int> fail;
    Trie_Tree(){
        nodes.push_back(Node(-1));
    }
    std::vector<int> insert(std::string &word,int word_id){
        int node_id=0;
        std::vector<int> ids;
        for (char & i : word){
            node_id=min_insert(i,node_id,word_id);
            ids.push_back(node_id);
        }
        nodes[ids.back()].terminate_node.push_back(word_id);
        return ids;
    }
    int min_insert(char ch,int node_id,int word_id){
        int c=(int)(ch-base);
        int next_id=nodes[node_id].next_node[c];
        if(next_id==-1){
            next_id=(int)nodes.size();
            nodes.push_back(Node(c));
        }
        nodes[next_id].parent_node=node_id;
        nodes[node_id].next_node[c]=next_id;
        // nodes[next_id].accept_node.push_back(word_id);
        nodes[node_id].accepet_count++;
        node_id=next_id;
        return node_id;
    }
    void aho(){
        fail.resize(nodes.size());
        std::vector<int> order = {0};
        order.reserve(nodes.size());
        for (int i = 0; i < (int)(order.size()); i++){
            int id = order[i];
            if (id == 0){
                fail[id] = 0;
            }
            else{
                int f = fail[nodes[id].parent_node];
                int c = nodes[id].char_number;
                while (f != fail[f] && nodes[f].next_node[c] == -1){
                    f = fail[f];
                }
                if (nodes[f].next_node[c] != -1 && nodes[f].next_node[c] != id) fail[id] = nodes[f].next_node[c];
                else fail[id] = 0;
            }
            for (int j = 0; j < char_size; j++){
                if (nodes[id].next_node[j] != -1) order.push_back(nodes[id].next_node[j]);
            }
        }
    }
};
}
using po167::Trie_Tree;
#line 3 "a.cpp"
#include <iostream>

int main(){
    std::string S;
    std::cin >> S;
    int N;
    std::cin >> N;
    po167::Trie_Tree<26,'a'> tt;
    for (int i = 0; i < N; i++){
        std::string t;
        std::cin >> t;
        tt.insert(t, i);
    }
    tt.aho();
    std::vector<int> taboo(tt.nodes.size());
    {
        std::vector<int> order = {0};
        for (int i = 0; i < (int)order.size(); i++){
            int a = order[i];
            if (!tt.nodes[a].terminate_node.empty()) taboo[a] = 1;
            if (taboo[tt.fail[a]]) taboo[a] = 1;
            for (int j = 0; j < 26; j++) if (tt.nodes[a].next_node[j] != -1){
                order.push_back(tt.nodes[a].next_node[j]);
            }
        }
    }
    int ans = 0;
    int r = 0;
    int node = 0;
    while (r != (int)S.size()){
        int c = S[r] - 'a';
        if (tt.nodes[node].next_node[c] == -1){
            if (node == 0) r++;
            node = tt.fail[node];
        }
        else{
            node = tt.nodes[node].next_node[c];
            r++;
        }
        if (taboo[node]){
            ans++;
            node = 0;
        }
    }
    std::cout << ans << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 23636
final_rank: 9

code_snippet: #include <bits/stdc++.h>
namespace po167{
template<const int char_size,int base>
struct Trie_Tree
{
    struct Node{
        std::array<int, char_size> next_node;
        std::vector<int> terminate_node;
        int parent_node;
        int char_number;
        int accepet_count;
        explicit Node(int c_):parent_node(-1),char_number(c_),accepet_count(0){
            for(int i=0;i<char_size;i++) next_node[i]=-1;
        }
    };
    std::vector<Node> nodes;
    std::vector<int> fail;
    Trie_Tree(){
        nodes.push_back(Node(-1));
    }
    std::vector<int> insert(std::string &word,int word_id){
        int node_id=0;
        std::vector<int> ids;
        for (char & i : word){
            node_id=min_insert(i,node_id,word_id);
            ids.push_back(node_id);
        }
        nodes[ids.back()].terminate_node.push_back(word_id);
        return ids;
    }
    int min_insert(char ch,int node_id,int word_id){
        int c=(int)(ch-base);
        int next_id=nodes[node_id].next_node[c];
        if(next_id==-1){
            next_id=(int)nodes.size();
            nodes.push_back(Node(c));
        }
        nodes[next_id].parent_node=node_id;
        nodes[node_id].next_node[c]=next_id;
        // nodes[next_id].accept_node.push_back(word_id);
        nodes[node_id].accepet_count++;
        node_id=next_id;
        return node_id;
    }
    void aho(){
        fail.resize(nodes.size());
        std::vector<int> order = {0};
        order.reserve(nodes.size());
        for (int i = 0; i < (int)(order.size()); i++){
            int id = order[i];
            if (id == 0){
                fail[id] = 0;
            }
            else{
                int f = fail[nodes[id].parent_node];
                int c = nodes[id].char_number;
                while (f != fail[f] && nodes[f].next_node[c] == -1){
                    f = fail[f];
                }
                if (nodes[f].next_node[c] != -1 && nodes[f].next_node[c] != id) fail[id] = nodes[f].next_node[c];
                else fail[id] = 0;
            }
            for (int j = 0; j < char_size; j++){
                if (nodes[id].next_node[j] != -1) order.push_back(nodes[id].next_node[j]);
            }
        }
    }
};
}
using po167::Trie_Tree;

int main(){
    std::string S;
    std::cin >> S;
    int N;
    std::cin >> N;
    po167::Trie_Tree<26,'a'> tt;
    for (int i = 0; i < N; i++){
        std::string t;
        std::cin >> t;
        tt.insert(t, i);
    }
    tt.aho();
    std::vector<int> taboo(tt.nodes.size());
    {
        std::vector<int> order = {0};
        for (int i = 0; i < (int)order.size(); i++){
            int a = order[i];
            if (!tt.nodes[a].terminate_node.empty()) taboo[a] = 1;
            if (taboo[tt.fail[a]]) taboo[a] = 1;
            for (int j = 0; j < 26; j++) if (tt.nodes[a].next_node[j] != -1){
                order.push_back(tt.nodes[a].next_node[j]);
            }
        }
    }
    int ans = 0;
    int r = 0;
    int node = 0;
    while (r != (int)S.size()){
        int c = S[r] - 'a';
        if (tt.nodes[node].next_node[c] == -1){
            if (node == 0) r++;
            node = tt.fail[node];
        }
        else{
            node = tt.nodes[node].next_node[c];
            r++;
        }
        if (taboo[node]){
            ans++;
            node = 0;
        }
    }
    std::cout << ans << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 22696
final_rank: 7

code_snippet: #include <bits/stdc++.h>




namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa


namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
using namespace zawa;

struct Node {
    std::array<int, 26> ch;
    int suffixLink{-1}, par{-1};
    char prevEdge{};
    bool terminal{};
    Node() {
        ch.fill(-1);
    }
    std::vector<std::pair<char, int>> childs() const {
        std::vector<std::pair<char, int>> res;
        for (int i{} ; i < 26 ; i++) if (ch[i] != -1) {
            res.emplace_back(i + 'a', ch[i]);
        }
        return res;
    }
};

std::vector<Node> Trie;

void Insert(const std::string& S) {
    // std::cout << S << " insert" << std::endl;
    int cur{}, i{};
    for ( ; i < (int)S.size() ; i++) {
        if (Trie[cur].ch[S[i] - 'a'] == -1) break;
        else cur = Trie[cur].ch[S[i] - 'a'];
    }
    for ( ; i < (int)S.size() ; i++) {
        int x{(int)Trie.size()};
        Trie.emplace_back();
        Trie[cur].ch[S[i] - 'a'] = x;
        Trie[x].par = cur;
        Trie[x].prevEdge = S[i];
        cur = x;
        // std::cout << x << " is " << S[i] << std::endl;
    }
    Trie[cur].terminal = true;
}

void BuildTrie(const std::vector<std::string>& S) {
    Trie.emplace_back(); 
    for (const auto& s : S) Insert(s);
}

void MakeSuffixLink() {
    Trie[0].suffixLink = 0;
    std::queue<int> que;
    for (const auto& x : Trie[0].childs()) que.emplace(x.second);
    while (que.size()) {
        auto v{que.front()};
        que.pop();
        // std::cout << v << " suflink is ";
        if (Trie[v].par == 0) {
            Trie[v].suffixLink = 0;
            // std::cout << 0 << std::endl;
        }
        else {
            int x{Trie[v].par};
            x = Trie[x].suffixLink;
            while (Trie[x].ch[Trie[v].prevEdge - 'a'] == -1 and Trie[x].suffixLink != x) {
                x = Trie[x].suffixLink;
            }
            if (Trie[x].ch[Trie[v].prevEdge - 'a'] == -1) {
                Trie[v].suffixLink = 0;
            }
            else if (Trie[x].ch[Trie[v].prevEdge - 'a'] == v) {
                Trie[v].suffixLink = 0;
            }
            else {
                x = Trie[x].ch[Trie[v].prevEdge - 'a'];
                Trie[v].suffixLink = x;
            }
            { // ここは消す
                if (Trie[Trie[v].suffixLink].terminal) Trie[v].terminal = true;
            }
        }
        for (const auto& x : Trie[v].childs()) que.emplace(x.second);
    }
}

int main() {
    SetFastIO();

    std::string S;
    std::cin >> S;
    int N;
    std::cin >> N;
    std::vector<std::string> T(N);
    for (auto& t : T) std::cin >> t;
    BuildTrie(T);
    MakeSuffixLink();
    int ans{};
    int cur{};
    for (auto c : S) {
        // std::cout << S[i] << ' ' << cur << ' ';
        while (cur != 0 and Trie[cur].ch[c - 'a'] == -1) {
            assert(cur != Trie[cur].suffixLink);
            if (Trie[cur].terminal) {
                cur = 0;
                // std::cout << "find " << i << ' ' << cur << ' ' << S[i] << std::endl;
                ans++;
            }
            cur = Trie[cur].suffixLink;
        }
        // std::cout << "goes to " << cur << std::endl;
        if (cur == 0 and Trie[cur].ch[c - 'a'] == -1) {
            continue;
        }
        else {
            assert(Trie[cur].ch[c - 'a'] != -1);
            cur = Trie[cur].ch[c - 'a'];
            if (Trie[cur].terminal) {
                // std::cout << "find " << i << ' ' << cur << ' ' << S[i] << std::endl;
                ans++;
                cur = 0;
            }
        }
    }
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 20144
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using u64 = unsigned long long;
constexpr u64 MOD{(1LL << 61) - 1};
constexpr u64 base{1283759723851LL};
constexpr u64 MASK30{(1LL << 30) - 1};
constexpr u64 MASK31{(1LL << 31) - 1};

u64 modulo(u64 v) {
    u64 res{(v >> 61) + (v & MOD)};
    res = (res >= MOD ? res - MOD : res);
    return res;
}

u64 unsafeMult(u64 a, u64 b) {
    u64 fa{a >> 31}, fb{b >> 31};
    u64 ba{a & MASK31}, bb{b & MASK31};
    u64 mid{fa * bb + fb * ba};
    return u64{2}*fa*fb+(mid >> 30)+((mid & MASK30) << 31) + ba*bb;
}

u64 mult(u64 a, u64 b) {
    return modulo(unsafeMult(a, b));
}

struct data {
    int len{};
    u64 pow{}, hash{};
    data() : len{}, hash{}, pow{} {}
    data(char c) : len{1}, hash{(u64)c - (u64)'a'}, pow{base} {}
    data(int len, u64 hash, u64 pow) : len{len}, hash{hash}, pow{pow} {}
};

struct M {
    using Element = data;
    static data operation(const data& A, const data& B) {
        return data{
            A.len + B.len,
            modulo(unsafeMult(A.hash, B.pow) + B.hash),
            mult(A.pow, B.pow)
        };
    }
    static data convert(const std::string& S) {
        data res{};
        for (auto c : S) res = operation(res, data(c));
        return res;
    }
};

template <class S>
class SWAG {
public:
    using V = typename S::Element;
private:
    std::vector<V> front{}, back{};
    std::vector<V> raw{};
    void move() {
        if (front.empty()) {
            while (back.size()) {
                back.pop_back();
                V v{raw.back()};
                raw.pop_back();
                front.push_back(front.size() ? S::operation(v, front.back()) : v);
            }
        }
    }
public:
    SWAG() = default;
    void push(const V& v) {
        raw.emplace_back(v);
        back.emplace_back(back.size() ? S::operation(back.back(), v) : v);
    }
    void pop() {
        move();
        assert(front.size());
        front.pop_back();
    }
    size_t size() const {
        return front.size() + back.size();
    }
    V product() const {
        assert(front.size() or back.size());
        if (front.empty()) return back.back();
        if (back.empty()) return front.back();
        return S::operation(front.back(), back.back());
    }
};

int main() {
    std::string S;
    std::cin >> S;
    int N;
    std::cin >> N;
    std::vector<std::string> P(N);
    for (auto& p : P) std::cin >> p;
    std::vector<std::vector<int>> idx(S.size() + 1);
    for (int i{} ; i < (int)P.size() ; i++) {
        if (P[i].size() > S.size()) continue;
        idx[P[i].size()].push_back(i);
    }
    std::vector<int> R(S.size(), (int)S.size() + 1);
    for (int i{1} ; i <= (int)S.size() ; i++) {
        if (idx[i].empty()) continue;
        // std::cout << "start " << i << std::endl;
        std::vector<std::pair<data, int>> prod;
        std::unordered_map<u64, std::vector<int>> map;
        SWAG<M> swag;
        for (int j{} ; j < i ; j++) {
            swag.push(data{S[j]});
        }
        for (int j{i} ; j <= (int)S.size() ; j++) {
            assert(swag.size() == (size_t)i);
            map[swag.product().hash].emplace_back(j - i);
            if (j < (int)S.size()) {
                swag.pop();
                swag.push(data{S[j]});
            }
        }
        for (auto j : idx[i]) {
            u64 hash{M::convert(P[j]).hash};     
            auto it{map.find(hash)};
            if (it == map.end()) continue;
            for (auto x : it->second) {
                R[x] = std::min(R[x], x + i);
            }
        }
    }
    std::vector<std::pair<int, int>> range;
    range.reserve(S.size());
    for (int i{} ; i < (int)S.size() ; i++) {
        if (R[i] == (int)S.size() + 1) continue;
        range.emplace_back(R[i], i);
    }
    std::sort(range.begin(), range.end()); 
    int ans{}, last{-1};
    for (auto [r, l] : range) {
        if (l <= last and last < r) continue;
        ans++;
        last = r - 1;
    }
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 1690
memory_kb: 14856
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using u64 = unsigned long long;
constexpr u64 MOD{(1LL << 61) - 1};
constexpr u64 base{1283759723851LL};
constexpr u64 MASK30{(1LL << 30) - 1};
constexpr u64 MASK31{(1LL << 31) - 1};

u64 modulo(u64 v) {
    u64 res{(v >> 61) + (v & MOD)};
    res = (res >= MOD ? res - MOD : res);
    return res;
}

u64 unsafeMult(u64 a, u64 b) {
    u64 fa{a >> 31}, fb{b >> 31};
    u64 ba{a & MASK31}, bb{b & MASK31};
    u64 mid{fa * bb + fb * ba};
    return u64{2}*fa*fb+(mid >> 30)+((mid & MASK30) << 31) + ba*bb;
}

u64 mult(u64 a, u64 b) {
    return modulo(unsafeMult(a, b));
}

struct data {
    int len{};
    u64 pow{}, hash{};
    data() : len{}, hash{}, pow{} {}
    data(char c) : len{1}, hash{(u64)c - (u64)'a'}, pow{base} {}
    data(int len, u64 hash, u64 pow) : len{len}, hash{hash}, pow{pow} {}
};

struct M {
    using Element = data;
    static data operation(const data& A, const data& B) {
        return data{
            A.len + B.len,
            modulo(unsafeMult(A.hash, B.pow) + B.hash),
            mult(A.pow, B.pow)
        };
    }
    static data convert(const std::string& S) {
        data res{};
        for (auto c : S) res = operation(res, data(c));
        return res;
    }
};

template <class S>
class SWAG {
public:
    using V = typename S::Element;
private:
    std::stack<V> front{}, back{};
    std::stack<V> raw{};
    void move() {
        if (front.empty()) {
            while (back.size()) {
                back.pop();
                V v{raw.top()};
                raw.pop();
                front.push(front.size() ? S::operation(v, front.top()) : v);
            }
        }
    }
public:
    SWAG() = default;
    void push(const V& v) {
        raw.emplace(v);
        back.emplace(back.size() ? S::operation(back.top(), v) : v);
    }
    void pop() {
        move();
        assert(front.size());
        front.pop();
    }
    size_t size() const {
        return front.size() + back.size();
    }
    V product() const {
        assert(front.size() or back.size());
        if (front.empty()) return back.top();
        if (back.empty()) return front.top();
        return S::operation(front.top(), back.top());
    }
};

int main() {
    std::string S;
    std::cin >> S;
    int N;
    std::cin >> N;
    std::vector<std::string> P(N);
    for (auto& p : P) std::cin >> p;
    std::vector<std::vector<int>> idx(S.size() + 1);
    for (int i{} ; i < (int)P.size() ; i++) {
        if (P[i].size() > S.size()) continue;
        idx[P[i].size()].push_back(i);
    }
    std::vector<int> R(S.size(), (int)S.size() + 1);
    for (int i{1} ; i <= (int)S.size() ; i++) {
        if (idx[i].empty()) continue;
        // std::cout << "start " << i << std::endl;
        std::vector<std::pair<data, int>> prod;
        std::unordered_map<u64, std::vector<int>> map;
        SWAG<M> swag;
        for (int j{} ; j < i ; j++) {
            swag.push(data{S[j]});
        }
        for (int j{i} ; j <= (int)S.size() ; j++) {
            assert(swag.size() == (size_t)i);
            map[swag.product().hash].emplace_back(j - i);
            if (j < (int)S.size()) {
                swag.pop();
                swag.push(data{S[j]});
            }
        }
        for (auto j : idx[i]) {
            u64 hash{M::convert(P[j]).hash};     
            auto it{map.find(hash)};
            if (it == map.end()) continue;
            for (auto x : it->second) {
                R[x] = std::min(R[x], x + i);
            }
        }
    }
    std::vector<std::pair<int, int>> range;
    range.reserve(S.size());
    for (int i{} ; i < (int)S.size() ; i++) {
        if (R[i] == (int)S.size() + 1) continue;
        range.emplace_back(R[i], i);
    }
    std::sort(range.begin(), range.end()); 
    int ans{}, last{-1};
    for (auto [r, l] : range) {
        if (l <= last and last < r) continue;
        ans++;
        last = r - 1;
    }
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 1860
memory_kb: 14880
final_rank: 15

code_snippet: #include <bits/stdc++.h>

constexpr int N = 100005;
constexpr long long MOD = (1LL << 61) - 1;
constexpr long long BASE = 514;
long long BASE_POW[N];
long long BASE_POW_INV[N];

using i128 = __int128_t;

long long mod_pow(long long base, long long exp) {
    long long res = 1;
    while (exp > 0) {
        if (exp & 1) {
            res = ((i128)res * base) % MOD;
        }
        base = (i128)base * base % MOD;
        exp >>= 1;
    }
    return res;
}

void init() {
    BASE_POW[0] = 1;
    for (int i = 0; i + 1 < N; i++) {
        BASE_POW[i + 1] = ((i128)BASE_POW[i] * BASE) % MOD;
    }
    BASE_POW_INV[N - 1] = mod_pow(BASE_POW[N - 1], MOD - 2);
    for (int i = N - 1; i > 0; i--) {
        BASE_POW_INV[i - 1] = ((i128)BASE_POW_INV[i] * BASE) % MOD;
    }
}

long long to_hash(const std::string& s) {
    long long hash = 0;
    int n = s.size();
    for (int i = 0; i < n; i++) {
        hash += (i128)s[i] * BASE_POW[i] % MOD;
        if (hash >= MOD) hash -= MOD;
    }
    return hash;
}


struct RH {
    std::vector<long long> table;
    RH(const std::string& s): table(s.size() + 1) {
        int n = s.size();
        for (int i = 0; i < n; i++) {
            table[i + 1] = table[i] + (i128)s[i] * BASE_POW[i] % MOD;
            if (table[i + 1] >= MOD) table[i + 1] -= MOD;
        }
    }
    long long hash(int left, int right) {
        long long hash = table[right] - table[left];
        if (hash < 0) hash += MOD;
        hash = (i128)hash * BASE_POW_INV[left] % MOD;
        return hash;
    }
};


int main() {
    init();
    std::string s;
    std::cin >> s;
    int m;
    std::cin >> m;
    std::vector<std::pair<int, long long>> len_hash;

    for (int i = 0; i < m; i++) {
        std::string t;
        std::cin >> t;
        int len = t.size();
        auto hash = to_hash(t);
        len_hash.emplace_back(len, hash);
    }
    std::sort(len_hash.begin(), len_hash.end());
    RH rh(s);
    const int INF = 1e9;
    std::vector<int> min_right(s.size(), INF);
    for (int l = 0, r = 0; l < m; l = r) {
        while (r < m && len_hash[l].first == len_hash[r].first) r++;
        int len = len_hash[l].first;
        std::unordered_set<long long> set;
        for (int i = l; i < r; i++) set.insert(len_hash[i].second);
        for (int left = 0; left + len <= (int)s.size(); left++) {
            auto hash = rh.hash(left, left + len);
            if (set.find(hash) != set.end()) {
                min_right[left] = std::min(min_right[left], left + len);
            }
        }
    }
    std::vector<std::pair<int, int>> intervals;
    for (int i = 0; i < (int)s.size(); i++) if (min_right[i] != INF) intervals.emplace_back(i, min_right[i]);
    if (intervals.empty()) {
        std::cout << 0 << std::endl;
        return 0;
    }
    std::sort(intervals.begin(), intervals.end(), [](std::pair<int, int> lhs, std::pair<int, int> rhs) {
            if (lhs.second == rhs.second) return lhs.first < rhs.first;
            return lhs.second < rhs.second;
            });
    int nw = intervals[0].second-1;
    int ans = 1;
    for(int i = 0; intervals.size() > i; i++){
       if(intervals[i].first > nw){
           ans++;
           nw = intervals[i].second-1;
       } 
    }
    std::cout << ans << std::endl;
}
accuracy: 1
time_ms: 1360
memory_kb: 7368
final_rank: 12

code_snippet: #include <bits/stdc++.h>

constexpr int N = 100005;
constexpr long long MOD = (1LL << 61) - 1;
constexpr long long BASE = 514;
long long BASE_POW[N];
long long BASE_POW_INV[N];

using i128 = __int128_t;

long long mod_pow(long long base, long long exp) {
    long long res = 1;
    while (exp > 0) {
        if (exp & 1) {
            res = ((i128)res * base) % MOD;
        }
        base = (i128)base * base % MOD;
        exp >>= 1;
    }
    return res;
}

void init() {
    BASE_POW[0] = 1;
    for (int i = 0; i + 1 < N; i++) {
        BASE_POW[i + 1] = ((i128)BASE_POW[i] * BASE) % MOD;
    }
    BASE_POW_INV[N - 1] = mod_pow(BASE_POW[N - 1], MOD - 2);
    for (int i = N - 1; i > 0; i--) {
        BASE_POW_INV[i - 1] = ((i128)BASE_POW_INV[i] * BASE) % MOD;
    }
}

long long to_hash(const std::string& s) {
    long long hash = 0;
    int n = s.size();
    for (int i = 0; i < n; i++) {
        hash += (i128)s[i] * BASE_POW[i] % MOD;
        if (hash >= MOD) hash -= MOD;
    }
    return hash;
}


struct RH {
    std::vector<long long> table;
    RH(const std::string& s): table(s.size() + 1) {
        int n = s.size();
        for (int i = 0; i < n; i++) {
            table[i + 1] = table[i] + (i128)s[i] * BASE_POW[i] % MOD;
            if (table[i + 1] >= MOD) table[i + 1] -= MOD;
        }
    }
    long long hash(int left, int right) {
        long long hash = table[right] - table[left];
        if (hash < 0) hash += MOD;
        hash = (i128)hash * BASE_POW_INV[left] % MOD;
        return hash;
    }
};


int main() {
    init();
    std::string s;
    std::cin >> s;
    int m;
    std::cin >> m;
    std::vector<std::pair<int, long long>> len_hash;

    for (int i = 0; i < m; i++) {
        std::string t;
        std::cin >> t;
        int len = t.size();
        auto hash = to_hash(t);
        len_hash.emplace_back(len, hash);
    }
    std::sort(len_hash.begin(), len_hash.end());
    RH rh(s);
    const int INF = 1e9;
    std::vector<int> min_right(s.size(), INF);
    for (int l = 0, r = 0; l < m; l = r) {
        while (r < m && len_hash[l].first == len_hash[r].first) r++;
        int len = len_hash[l].first;
        std::unordered_set<long long> set;
        for (int i = l; i < r; i++) set.insert(len_hash[i].second);
        for (int left = 0; left + len <= (int)s.size(); left++) {
            auto hash = rh.hash(left, left + len);
            if (set.find(hash) != set.end()) {
                min_right[left] = std::min(min_right[left], left + len);
            }
        }
    }
    std::vector<std::pair<int, int>> intervals;
    for (int i = 0; i < (int)s.size(); i++) if (min_right[i] != INF) intervals.emplace_back(i, min_right[i]);
    if (intervals.empty()) {
        std::cout << 0 << std::endl;
        return 0;
    }
    std::sort(intervals.begin(), intervals.end(), [](std::pair<int, int> lhs, std::pair<int, int> rhs) {
            if (lhs.second == rhs.second) return lhs.first < rhs.first;
            return lhs.second < rhs.second;
            });
    int nw = intervals[0].second-1;
    int ans = 1;
    for(int i = 0; intervals.size() > i; i++){
       if(intervals[i].first > nw){
           ans++;
           nw = intervals[i].second-1;
       } 
    }
    std::cout << ans << std::endl;
}
accuracy: 1
time_ms: 1360
memory_kb: 7388
final_rank: 13

code_snippet: #define _USE_MATH_DEFINES  // M_PI等のフラグ
#include <bits/stdc++.h>
#define MOD 1000000007
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define intceil(a,b) ((a+(b-1))/(b))
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<long,long>;
const long long INF = LONG_LONG_MAX - 1001001001001001;
void chmax(ll& x, ll y) { x = max(x,y); }
void chmin(ll& x, ll y) { x = min(x,y); }
string vs = "URDL";  // 上右下左
vector<ll> vy = { -1, 0, 1, 0 };
vector<ll> vx = { 0, 1, 0, -1 };

/***ローリングハッシュ法で文字列検索
 * 計算量はO(N+M)
 ***/
const unsigned long long B = 100000007;  // ハッシュの基数

/***文字列s1はs2に含まれているか？
 * Returns:
 *  含まれている場合、一致箇所の開始位置であるs2のインデックスを返す
 *  含まれていなかった場合、-1を返す
 **/
long long contain(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();

    if (s1_len > s2_len) return -1;

    // Bのs1_len乗を計算する
    unsigned long long t = 1;
    for (long long i=0; i<s1_len; i++) t *= B;

    // s1とs2の最初のs1_len文字に関するハッシュ値を計算する
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    for (long long i=0; i<s1_len; i++) s1h = s1h * B + s1[i];
    for (long long i=0; i<s1_len; i++) s2h = s2h * B + s2[i];

    // s2の場所を1つずつ進めながらハッシュ値をチェック
    for (long long i=0; i+s1_len<=s2_len; i++) {
        if (s1h == s2h) return i;  // s2のi文字目からのs1_len文字が一致
        if (i+s1_len < s2_len) s2h = s2h * B + s2[i+s1_len] - s2[i]*t;
    }

    return -1;
 }


/***文字列s1の末尾とs2の先頭を何文字重ねることができるか？
 * Returns:
 *  重なっている文字数を返す。
 *  重なっていなかった場合、0を返す
 ***/
long long overlap(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();
    long long ans = 0;
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    unsigned long long t = 1;

    for (long long i=1; i<=min(s1_len, s2_len); i++) {
        s1h = s1h + s1[s1_len-i]*t;  // s1の末尾i文字のハッシュ値
        s2h = s2h * B + s2[i-1];     // s2の先頭i文字のハッシュ値
        if (s1h == s2h) ans = i;
        t *= B;
    }

    return ans;
}

void solve() {
    string S; cin >> S;
    ll N; cin >> N;
    vector<string> P(N);
    for(ll i=0; i<N; i++) {
        cin >> P[i];
    }

    vector<pair<ll,ll>> data; // (始端, 終端)
    for(ll i=0; i<N; i++) {
        ll start = 0;
        while(true) {
            ll idx = contain(P[i], S.substr(start));
            if (idx == -1) break;
            data.push_back({start+idx, start+idx+(ll)P[i].size()-1});
            start += idx + (ll)P[i].size();
            if (start >= (ll)S.size()) break;
        }
    }
    // データが一個もないなら終了
    if (data.size() == 0) {
        cout << 0 << endl;
        return;
    }

    // 比較関数（pairのsecond昇順）
    auto comp = [&](const pair<ll,ll> &p1, const pair<ll,ll> &p2) -> bool {
        return p1.second < p2.second;
    };
    sort(data.begin(), data.end(), comp);

    // 区間スケジューリング問題
    ll ans = 1;
    ll last_r = data[0].second;
    for(ll i=1; i<(ll)data.size(); i++) {
        auto[l, r] = data[i];
        if (l <= last_r) continue;
        last_r = r;
        ans++;
    }
    cout << ans << endl;
}


int main() {
    solve();
    return 0;
}
accuracy: 0.5111111111111111
time_ms: 1360
memory_kb: 9280
final_rank: 18

code_snippet: #define _USE_MATH_DEFINES  // M_PI等のフラグ
#include <bits/stdc++.h>
#define MOD 1000000007
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define intceil(a,b) ((a+(b-1))/(b))
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<long,long>;
const long long INF = LONG_LONG_MAX - 1001001001001001;
void chmax(ll& x, ll y) { x = max(x,y); }
void chmin(ll& x, ll y) { x = min(x,y); }
string vs = "URDL";  // 上右下左
vector<ll> vy = { -1, 0, 1, 0 };
vector<ll> vx = { 0, 1, 0, -1 };

/***ローリングハッシュ法で文字列検索
 * 計算量はO(N+M)
 ***/
const unsigned long long B = 100000007;  // ハッシュの基数

/***文字列s1はs2に含まれているか？
 * Returns:
 *  含まれている場合、一致箇所の開始位置であるs2のインデックスを返す
 *  含まれていなかった場合、-1を返す
 **/
long long contain(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();

    if (s1_len > s2_len) return -1;

    // Bのs1_len乗を計算する
    unsigned long long t = 1;
    for (long long i=0; i<s1_len; i++) t *= B;

    // s1とs2の最初のs1_len文字に関するハッシュ値を計算する
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    for (long long i=0; i<s1_len; i++) s1h = s1h * B + s1[i];
    for (long long i=0; i<s1_len; i++) s2h = s2h * B + s2[i];

    // s2の場所を1つずつ進めながらハッシュ値をチェック
    for (long long i=0; i+s1_len<=s2_len; i++) {
        if (s1h == s2h) return i;  // s2のi文字目からのs1_len文字が一致
        if (i+s1_len < s2_len) s2h = s2h * B + s2[i+s1_len] - s2[i]*t;
    }

    return -1;
 }


/***文字列s1の末尾とs2の先頭を何文字重ねることができるか？
 * Returns:
 *  重なっている文字数を返す。
 *  重なっていなかった場合、0を返す
 ***/
long long overlap(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();
    long long ans = 0;
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    unsigned long long t = 1;

    for (long long i=1; i<=min(s1_len, s2_len); i++) {
        s1h = s1h + s1[s1_len-i]*t;  // s1の末尾i文字のハッシュ値
        s2h = s2h * B + s2[i-1];     // s2の先頭i文字のハッシュ値
        if (s1h == s2h) ans = i;
        t *= B;
    }

    return ans;
}

void solve() {
    string S; cin >> S;
    ll N; cin >> N;
    vector<string> P(N);
    for(ll i=0; i<N; i++) {
        cin >> P[i];
    }

    vector<pair<ll,ll>> data; // (始端, 終端)
    for(ll i=0; i<N; i++) {
        ll start = 0;
        while(true) {
            ll idx = contain(P[i], S.substr(start));
            if (idx == -1) break;
            data.push_back({start+idx, start+idx+(ll)P[i].size()-1});
            start += idx + 1;
            if (start >= (ll)S.size()) break;
        }
    }

    // 比較関数（pairのsecond昇順）
    auto comp = [&](const pair<ll,ll> &p1, const pair<ll,ll> &p2) -> bool {
        return p1.second < p2.second;
    };
    sort(data.begin(), data.end(), comp);

    // 区間スケジューリング問題
    ll ans = 1;
    ll last_r = data[0].second;
    for(ll i=1; i<(ll)data.size(); i++) {
        auto[l, r] = data[i];
        if (l <= last_r) continue;
        last_r = r;
        ans++;
    }
    cout << ans << endl;
}


int main() {
    solve();
    return 0;
}
accuracy: 0.08888888888888889
time_ms: 340
memory_kb: 4444
final_rank: 19

code_snippet: #define _USE_MATH_DEFINES  // M_PI等のフラグ
#include <bits/stdc++.h>
#define MOD 1000000007
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define intceil(a,b) ((a+(b-1))/(b))
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<long,long>;
const long long INF = LONG_LONG_MAX - 1001001001001001;
void chmax(ll& x, ll y) { x = max(x,y); }
void chmin(ll& x, ll y) { x = min(x,y); }
string vs = "URDL";  // 上右下左
vector<ll> vy = { -1, 0, 1, 0 };
vector<ll> vx = { 0, 1, 0, -1 };

/***ローリングハッシュ法で文字列検索
 * 計算量はO(N+M)
 ***/
const unsigned long long B = 100000007;  // ハッシュの基数

/***文字列s1はs2に含まれているか？
 * Returns:
 *  含まれている場合、一致箇所の開始位置であるs2のインデックスを返す
 *  含まれていなかった場合、-1を返す
 **/
long long contain(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();

    if (s1_len > s2_len) return -1;

    // Bのs1_len乗を計算する
    unsigned long long t = 1;
    for (long long i=0; i<s1_len; i++) t *= B;

    // s1とs2の最初のs1_len文字に関するハッシュ値を計算する
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    for (long long i=0; i<s1_len; i++) s1h = s1h * B + s1[i];
    for (long long i=0; i<s1_len; i++) s2h = s2h * B + s2[i];

    // s2の場所を1つずつ進めながらハッシュ値をチェック
    for (long long i=0; i+s1_len<=s2_len; i++) {
        if (s1h == s2h) return i;  // s2のi文字目からのs1_len文字が一致
        if (i+s1_len < s2_len) s2h = s2h * B + s2[i+s1_len] - s2[i]*t;
    }

    return -1;
 }


/***文字列s1の末尾とs2の先頭を何文字重ねることができるか？
 * Returns:
 *  重なっている文字数を返す。
 *  重なっていなかった場合、0を返す
 ***/
long long overlap(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();
    long long ans = 0;
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    unsigned long long t = 1;

    for (long long i=1; i<=min(s1_len, s2_len); i++) {
        s1h = s1h + s1[s1_len-i]*t;  // s1の末尾i文字のハッシュ値
        s2h = s2h * B + s2[i-1];     // s2の先頭i文字のハッシュ値
        if (s1h == s2h) ans = i;
        t *= B;
    }

    return ans;
}

void solve() {
    string S; cin >> S;
    ll N; cin >> N;
    vector<string> P(N);
    for(ll i=0; i<N; i++) {
        cin >> P[i];
    }

    vector<pair<ll,ll>> data; // (始端, 終端)
    for(ll i=0; i<N; i++) {
        ll start = 0;
        while(true) {
            ll idx = contain(P[i], S.substr(start));
            if (idx == -1) break;
            data.push_back({start+idx, start+idx+(ll)P[i].size()-1});
            start += idx + 1;
            if (start >= (ll)S.size()) break;
        }
    }

    // 比較関数（pairのsecond昇順）
    auto comp = [&](const pair<ll,ll> &p1, const pair<ll,ll> &p2) -> bool {
        return p1.second < p2.second;
    };
    sort(data.begin(), data.end(), comp);

    // 区間スケジューリング問題
    ll ans = 1;
    ll last_r = data[0].second;
    for(ll i=1; i<(ll)data.size(); i++) {
        auto[l, r] = data[i];
        if (l < last_r) continue;
        last_r = r;
        ans++;
    }
    cout << ans << endl;
}


int main() {
    solve();
    return 0;
}
accuracy: 0.06666666666666667
time_ms: 340
memory_kb: 4420
final_rank: 20

code_snippet: #line 1 "a.cpp"
#define PROBLEM ""
#line 2 "/home/kuhaku/home/github/algo/lib/template/template.hpp"
#pragma GCC target("sse4.2,avx2,bmi2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr int MOD = 1000000007;
constexpr int MOD_N = 998244353;
constexpr double EPS = 1e-7;
constexpr double PI = M_PI;
#line 2 "/home/kuhaku/home/github/algo/lib/string/aho_corasick.hpp"

template <int char_size, int base>
struct aho_corasick {
  private:
    struct _node {
        std::vector<int> next_node;
        _node() : next_node(char_size, -1) {}

        int next(int x) const { return this->next_node[x]; }
    };

  public:
    using node_type = _node;

    aho_corasick() : nodes() { this->nodes.emplace_back(); }

    int size() const noexcept { return this->nodes.size(); }

    std::vector<int> build() {
        this->failure = std::vector<int>(nodes.size(), 0);
        queue<int> que;
        for (int i = 0; i < char_size; ++i) {
            int next_root = this->nodes[0].next(i);
            if (next_root != -1) {
                que.emplace(next_root);
            }
        }

        while (!que.empty()) {
            int x = que.front();
            que.pop();
            for (int i = 0; i < char_size; ++i) {
                int next_x = this->nodes[x].next(i);
                if (next_x != -1) {
                    que.emplace(next_x);
                    int y = x;
                    do {
                        y = this->failure[y];
                        int next_y = this->nodes[y].next(i);
                        if (next_y != -1) {
                            this->failure[next_x] = next_y;
                            break;
                        }
                    } while (y != 0);
                }
            }
        }
        return this->failure;
    }

    std::vector<int> insert(const string &word) {
        std::vector<int> res;
        int node_id = 0;
        for (int i = 0; i < (int)word.size(); ++i) {
            int c = word[i] - base;
            int &next_id = this->nodes[node_id].next_node[c];
            if (next_id == -1) {
                next_id = this->nodes.size();
                this->nodes.emplace_back();
            }
            node_id = next_id;
            res.emplace_back(node_id);
        }
        return res;
    }

    int search(const char c, int now = 0) {
        int next_id = this->nodes[now].next(c - base);
        while (next_id == -1 && now != 0) {
            now = this->failure[now];
            next_id = this->nodes[now].next(c - base);
        }
        return next_id != -1 ? next_id : 0;
    }

    std::vector<int> search(const std::string &str, int now = 0) {
        std::vector<int> res;
        res.emplace_back(now);
        for (auto c : str) {
            now = search(c, now);
            res.emplace_back(now);
        }
        return res;
    }

    node_type get_node(int node_id) const {
        assert(0 <= node_id && node_id < (int)this->nodes.size());
        return this->nodes[node_id];
    }

  private:
    std::vector<node_type> nodes;
    std::vector<int> failure;
};
#line 3 "/home/kuhaku/home/github/algo/lib/template/macro.hpp"
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
#line 3 "/home/kuhaku/home/github/algo/lib/template/sonic.hpp"
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
    }

    constexpr void operator()() const {}
} sonic;
#line 5 "/home/kuhaku/home/github/algo/lib/template/atcoder.hpp"
using ll = int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) {
        os << (it == v.begin() ? "" : " ") << *it;
    }
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0) return std::vector<T>(arg, x);
    else return std::vector(arg, make_vector<T>(x, args...));
}
void setp(int n) {
    std::cout << std::fixed << std::setprecision(n);
}
void Yes(bool is_correct = true) {
    std::cout << (is_correct ? "Yes" : "No") << '\n';
}
void No(bool is_not_correct = true) {
    Yes(!is_not_correct);
}
void YES(bool is_correct = true) {
    std::cout << (is_correct ? "YES" : "NO") << '\n';
}
void NO(bool is_not_correct = true) {
    YES(!is_not_correct);
}
void Takahashi(bool is_correct = true) {
    std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n';
}
void Aoki(bool is_not_correct = true) {
    Takahashi(!is_not_correct);
}
#line 3 "/home/kuhaku/home/github/algo/lib/graph/graph.hpp"

/**
 * @brief 重み付きグラフ
 *
 * @tparam T 辺の重みの型
 */
template <class T>
struct Graph {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to(), _weight() {}
        constexpr _edge(int from, int to, T weight) : _from(from), _to(to), _weight(weight) {}
        constexpr bool operator<(const _edge &rhs) const { return this->weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }

        constexpr int from() const { return this->_from; }
        constexpr int to() const { return this->_to; }
        constexpr T weight() const { return this->_weight; }

      private:
        int _from, _to;
        T _weight;
    };

  public:
    using edge_type = typename Graph<T>::_edge;

    Graph(int v) : _size(v), edges(v) {}

    const auto &operator[](int i) const { return this->edges[i]; }
    auto &operator[](int i) { return this->edges[i]; }
    const auto begin() const { return this->edges.begin(); }
    auto begin() { return this->edges.begin(); }
    const auto end() const { return this->edges.end(); }
    auto end() { return this->edges.end(); }
    constexpr int size() const { return this->_size; }

    void add_edge(const edge_type &e) { this->edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to, T weight = T(1)) {
        this->edges[from].emplace_back(from, to, weight);
    }
    void add_edges(int from, int to, T weight = T(1)) {
        this->edges[from].emplace_back(from, to, weight);
        this->edges[to].emplace_back(to, from, weight);
    }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            cin >> from >> to >> weight;
            this->add_edge(from - base, to - base, weight);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            cin >> from >> to >> weight;
            this->add_edges(from - base, to - base, weight);
        }
    }

  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};

template <>
struct Graph<void> {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to() {}
        constexpr _edge(int from, int to) : _from(from), _to(to) {}

        constexpr int from() const { return this->_from; }
        constexpr int to() const { return this->_to; }
        constexpr int weight() const { return 1; }
        constexpr bool operator<(const _edge &rhs) const { return this->weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }

      private:
        int _from, _to;
    };

  public:
    using edge_type = typename Graph<void>::_edge;

    Graph(int v) : _size(v), edges(v) {}

    const auto &operator[](int i) const { return this->edges[i]; }
    auto &operator[](int i) { return this->edges[i]; }
    const auto begin() const { return this->edges.begin(); }
    auto begin() { return this->edges.begin(); }
    const auto end() const { return this->edges.end(); }
    auto end() { return this->edges.end(); }
    constexpr int size() const { return this->_size; }

    void add_edge(const edge_type &e) { this->edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to) { this->edges[from].emplace_back(from, to); }
    void add_edges(int from, int to) {
        this->edges[from].emplace_back(from, to);
        this->edges[to].emplace_back(to, from);
    }

    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            cin >> from >> to;
            this->add_edge(from - base, to - base);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            cin >> from >> to;
            this->add_edges(from - base, to - base);
        }
    }

  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
#line 3 "/home/kuhaku/home/github/algo/lib/tree/tree_function.hpp"

template <class T>
std::vector<int> tree_bfs(const Graph<T> &g, int r = 0) {
    int pos = 0;
    std::vector<int> res;
    std::vector<bool> visited(g.size());
    res.emplace_back(r);
    visited[r] = true;
    while (pos < res.size()) {
        auto index = res[pos++];
        for (auto &e : g[index]) {
            if (visited[e.to()]) continue;
            res.emplace_back(e.to());
            visited[e.to()] = true;
        }
    }
    return res;
}

std::vector<int> tree_bfs(const std::vector<int> &parents) {
    int n = parents.size();
    Graph<void> g(n);
    int r = 0;
    for (int i = 0; i < n; ++i) {
        if (parents[i] == -1 || parents[i] == i) {
            r = i;
            continue;
        }
        g.add_edges(i, parents[i]);
    }
    return tree_bfs(g, r);
}

template <class T>
std::vector<int> tree_dfs(const Graph<T> &g, int r = 0) {
    std::vector<int> res;
    auto dfs = [&g, &res](auto self, int index, int parent) {
        res.emplace_back(index);
        for (auto &e : g[index]) {
            if (e.to() == parent) continue;
            self(self, e.to(), index);
        }
    };
    dfs(dfs, r, -1);
    return res;
}

/**
 * @brief 木の距離を求める
 *
 * @tparam T 辺の重みの型
 * @tparam U 距離の型
 * @param g 木
 * @param r 根
 * @return std::vector<U> 各頂点の根からの距離
 */
template <class T, class U = T>
std::vector<U> tree_dist(const Graph<T> &g, int r = 0) {
    std::vector<U> res(g.size(), -1);
    std::stack<int> st;
    res[r] = 0;
    st.emplace(r);
    while (!st.empty()) {
        auto index = st.top();
        st.pop();
        for (auto &e : g[index]) {
            if (res[e.to()] != -1) continue;
            res[e.to()] = res[index] + e.weight();
            st.emplace(e.to());
        }
    }
    return res;
}

/**
 * @brief 木の頂点の親を求める
 *
 * @tparam T 辺の重みの型
 * @param g 木
 * @param r 根
 * @return std::vector<int>
 */
template <class T>
std::vector<int> tree_parent(const Graph<T> &g, int r = 0) {
    std::vector<int> res(g.size(), -1);
    std::stack<int> st;
    res[r] = r;
    st.emplace(r);
    while (!st.empty()) {
        auto index = st.top();
        st.pop();
        for (auto &e : g[index]) {
            if (res[e.to()] != -1) continue;
            res[e.to()] = index;
            st.emplace(e.to());
        }
    }
    res[r] = -1;
    return res;
}

/**
 * @brief 部分木の大きさを求める
 *
 * @tparam T 辺の重みの型
 * @param g グラフ
 * @param r 根
 * @return std::vector<int>
 */
template <class T>
std::vector<int> tree_subtree(const Graph<T> &g, int r = 0) {
    std::vector<int> res(g.size());
    auto dfs = [&g, &res](auto self, int index) {
        res[index] = 1;
        for (auto &e : g[index]) {
            if (res[e.to()] != 0) continue;
            res[index] += self(self, e.to());
        }
        return res[index];
    };
    dfs(dfs, r);
    return res;
}
#line 5 "a.cpp"

int main(void) {
    string s;
    cin >> s;
    int m;
    cin >> m;
    vector<string> t(m);
    cin >> t;
    aho_corasick<26, 'a'> aho;
    vector<vector<int>> correct;
    rep (i, m) {
        auto v = aho.insert(t[i]);
        correct.resize(aho.size());
        correct[v.back()].emplace_back(i);
    }
    auto failure = aho.build();
    auto bfs = tree_bfs(failure);
    for (auto x : bfs) {
        int y = failure[x];
        vector<int> v;
        set_union(correct[x].begin(), correct[x].end(), correct[y].begin(), correct[y].end(),
                  back_inserter(v));
        correct[x] = v;
    }
    auto res = aho.search(s);
    // ce(res);
    int ans = 0;
    int last = 0;
    int len = 0;
    for (auto x : res) {
        for (auto y : correct[x]) {
            if (last + t[y].size() <= len) {
                ++ans;
                last = len;
                break;
            }
        }
        ++len;
    }
    co(ans);

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 23484
final_rank: 8

code_snippet: #include <iostream>
using namespace std;

#include <algorithm>
#include <array>
#include <vector>

template<typename T, int alphabetSize, T min_element>
class Trie {

  struct node {
    std::array<int,alphabetSize> nxt;
    const int parent;
    node(int p) : nxt(), parent(p) {
      std::fill(nxt.begin(),nxt.end(),-1);
    }
    int operator[](int i) const {
      return nxt[i];
    }
  };

  const int root_idx;
  std::vector<node> nodes;
  
public:

  Trie() : root_idx(0), nodes(1,node(-1)) {}

  int add(const std::string& s){
    int v_id = root_idx;
    for(const char& c : s){
      if(nodes[v_id][c-min_element] == -1){
        nodes[v_id].nxt[c-min_element] = nodes.size();
        nodes.emplace_back(v_id);
      }
      v_id = nodes[v_id][c-min_element];
    }
    return v_id;
  }

  node& operator[](size_t i){
    return nodes[i];
  }

  int size(){
    return nodes.size();
  }
};

#include <array>
#include <cassert>
#include <iostream>
#include <vector>
#include <queue>
#include <numeric>
using namespace std;

template<typename T, int alphabetSize, T min_element>
class AhoCorasick {

  Trie<T,alphabetSize,min_element> trie;
  std::vector<int> suffix_cnt, failure;
  const int root_idx;
  const int num_pattern;

  void construct_failure(){
    std::queue<int> que;
    failure[root_idx] = root_idx;
    for(int i = 0; i < alphabetSize; ++i){
      if(trie[root_idx][i] == -1) continue;
      que.emplace(trie[root_idx][i]);
      failure[trie[root_idx][i]] = root_idx;
    }

    while(que.size()){
      int v = que.front();
      que.pop();
      suffix_cnt[v] += suffix_cnt[failure[v]];
      for(int i = 0; i < alphabetSize; ++i){
        if(trie[v][i] == -1) continue;
        que.push(trie[v][i]);
        int f = failure[v];
        while(f != -1 and trie[f][i] == -1){
          f = failure[f];
          if(f == root_idx) break;
        }
        failure[trie[v][i]] = (f == -1 or trie[f][i] == -1) ? root_idx : trie[f][i];
      }
    }
  }

public:

  AhoCorasick(const std::vector<std::string>& pattern)
    : trie(), suffix_cnt(), failure(), root_idx(0), num_pattern(pattern.size()) {
    vector<int> idx;
    for(const auto& p : pattern){
      idx.emplace_back(trie.add(p));
    }
    failure.resize(trie.size(),-1);
    suffix_cnt.resize(trie.size());
    for(auto e : idx)
      ++suffix_cnt[e];
    construct_failure();
  }

  int root(){ return root_idx; }

  std::pair<int,int> move(int cur, T c){
    int i = c - min_element;
    int nxt = cur;
    while(trie[nxt][i] == -1){
      if(nxt == root_idx) break;
      nxt = failure[nxt];
    }
    if(trie[nxt][i] >= 0) nxt = trie[nxt][i];
    else nxt = failure[nxt];
    return std::pair(suffix_cnt[nxt],nxt);
  }
};

int main(){
  string s;
  cin >> s;
  int n;
  cin >> n;
  vector<string> T(n);
  for(int i = 0; i < n; ++i)
    cin >> T[i];
  constexpr int alphabetSize = 26;
  AhoCorasick<char,alphabetSize,'a'> ahocora(T);
  int ans = 0, v = ahocora.root();
  for(auto c : s){
    auto [cnt,nxt] = ahocora.move(v,c);
    if(cnt){
      ++ans;
      nxt = ahocora.root();
    }
    v = nxt;
  }
  cout << ans << "\n";
}
accuracy: 1
time_ms: 10
memory_kb: 17280
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(), (v).end()
#define REP(i, n) for (int i = 0, i_len = n; i < i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

template <int64_t Modulus>
struct Modint {
    using mint = Modint;
    long long v;
    Modint() : v(0) {}
    Modint(long long x) {
        x %= Modulus;
        if (x < 0) x += Modulus;
        v = x;
    }
    const long long& val() const { return v; }
    // 代入演算子
    mint& operator+=(const mint rhs) {
        v += rhs.v;
        if (v >= Modulus) v -= Modulus;
        return *this;
    }
    mint& operator-=(const mint rhs) {
        if (v < rhs.v) v += Modulus;
        v -= rhs.v;
        return *this;
    }
    mint& operator*=(const mint rhs) {
        v = v * rhs.v % Modulus;
        return *this;
    }
    mint& operator/=(mint rhs) { return *this = *this * rhs.inv(); }
    // 累乗, 逆元
    mint pow(long long n) const {
        mint x = *this, res = 1;
        while (n) {
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }
    mint inv() const { return pow(Modulus - 2); }
    // 算術演算子
    mint operator+(const mint rhs) const { return mint(*this) += rhs; }
    mint operator-(const mint rhs) const { return mint(*this) -= rhs; }
    mint operator*(const mint rhs) const { return mint(*this) *= rhs; }
    mint operator/(const mint rhs) const { return mint(*this) /= rhs; }
    mint operator-() const { return mint() - *this; }  // 単項
    // 入出力ストリーム
    friend ostream& operator<<(ostream& os, const mint& p) { return os << p.v; }
    friend istream& operator>>(istream& is, mint& p) {
        long long t;
        is >> t;
        p = mint(t);
        return (is);
    }
};

using mint = Modint<MOD>;


struct AhoCorasick {
    static constexpr int C_SIZE = 26;    // C_SIZE  : 文字の種類数
    static constexpr int C_BEGIN = 'a';  // C_BEGIN : 開始文字
    static constexpr int ROOT = 0;
    struct Node {
        array<int, C_SIZE> to = {};  // to[c]=文字cによる遷移先ノード, 存在しなければ-1
        int id = -1;                 // そのノードでマッチする文字列のID, 存在しなければ-1
        int fail = ROOT;
        int sfx = ROOT;
        Node() { to.fill(-1); }
    };
    vector<Node> nodes;
    vector<string> patterns;  // 追加した文字列
    AhoCorasick() : nodes(1) {}
    // nodes[idx]から文字cで遷移したときの頂点のindex
    int next_state(int now, char c) {
        return nodes[now].to[c - C_BEGIN];
    }
    // 文字列の追加
    int insert(const string& str) {
        int now = ROOT;
        for (char c : str) {
            int k = c - C_BEGIN;
            int& nxt = nodes[now].to[k];
            if (nxt == -1) {
                now = nxt = int(nodes.size());
                nodes.push_back(Node());
            } else {
                now = nxt;
            }
        }
        nodes[now].id = int(patterns.size());
        patterns.push_back(str);
        return now;
    }
    void build() {
        queue<int> que;
        for (int& x : nodes[ROOT].to) {
            if (x == -1) {
                x = ROOT;
            } else {
                que.push(x);
            }
        }
        while (!que.empty()) {
            int now = que.front();
            que.pop();
            int fail = nodes[now].fail;
            for (int k = 0; k < C_SIZE; k++) {
                int& nxt = nodes[now].to[k];
                if (nxt == -1) {                          // 遷移失敗
                    nxt = nodes[fail].to[k];              // failure link で遷移してから遷移
                } else {                                  // 遷移成功
                    nodes[nxt].fail = nodes[fail].to[k];  // 遷移先のfailure linkを求める
                    que.push(nxt);
                }
            }
            nodes[now].sfx = (nodes[fail].id != -1 ? fail : nodes[fail].sfx);
        }
    }
    // stateにマッチするすべてのパターンのidを返す
    vector<int> match(int state) {
        vector<int> res;
        int now = state;
        while (now != ROOT) {
            if (nodes[now].id != -1) res.push_back(nodes[now].id);
            now = nodes[now].sfx;
        }
        return res;
    }
    // 文字列に対応するnodeのindexを検索, 存在しなければ-1
    vector<vector<int>> search(const string& str) {
        vector<vector<int>> res;
        int now = ROOT;
        for (auto c : str) {
            int nxt = next_state(now, c);
            res.emplace_back(match(nxt));
            now = nxt;
        }
        return res;
    }
};

int solve() {
    string s;
    int n;
    cin >> s >> n;
    AhoCorasick ac;
    for(int i=0;i<n;i++){
        string p;
        cin >> p;
        ac.insert(p);
    }
    ac.build();
    auto match = ac.search(s);
    int ans = 0, m = s.size(), ma = -1;
    for(int i=m-1; i>=0; i--){
        for(auto& id : match[i]){
            int len = ac.patterns[id].size();
            chmax(ma, i-len+1);
        }
        if(ma == i){
            ans++;
            ma = -1;
        }
    }
    cout << ans << endl;
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // while(!solve());
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 206716
final_rank: 17

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

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

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

namespace internal {

template <int char_size>
struct trie_node {
    int common;
    int nxt[char_size];
    std::vector<int> accept;
    trie_node() : common(0) { memset(nxt, -1, sizeof(nxt)); }
};

}  // namespace internal

template <int char_size, int margin>
struct trie {
   public:
    trie() { nodes.emplace_back(Node()); }

    void add(const std::string &str) {
        int idx = 0;
        for (const auto &c : str) {
            int val = c - margin;
            assert(0 <= val && val < char_size);
            if (nodes[idx].nxt[val] < 0) {
                nodes[idx].nxt[val] = int(nodes.size());
                nodes.emplace_back(Node());
            }
            idx = nodes[idx].nxt[val];
            nodes[idx].common++;
        }
        nodes[idx].accept.emplace_back(nodes[0].common++);
    }

    template <class F>
    void query(const std::string &str, int start, F func) const {
        int idx = 0;
        for (int i = start; i < int(str.size()); ++i) {
            int val = str[i] - margin;
            assert(0 <= val && val < char_size);
            int nxt = nodes[idx].nxt[val];
            if (nxt < 0) {
                return;
            }
            idx = nxt;
            for (const auto id : nodes[idx].accept) {
                func(id);
            }
        }
        return;
    }

    bool search(const std::string &str, int start, bool prefix = false) const {
        int idx = 0;
        for (int i = start; i < int(str.size()); ++i) {
            int val = str[i] - margin;
            assert(0 <= val && val < char_size);
            int nxt = nodes[idx].nxt[val];
            if (nxt < 0) {
                return -1;
            }
            idx = nxt;
        }
        return prefix ? true : (nodes[idx].accept.size() > 0);
    }

    int size() const { return int(nodes.size()); }

   private:
    using Node = internal::trie_node<char_size>;

   protected:
    std::vector<Node> nodes;
};

}  // namespace ebi

namespace ebi {

template <int char_size, int margin>
struct aho_corasick : trie<char_size + 1, margin> {
   private:
    void move_nxt(int &now, int val) {
        assert(0 <= val && val < char_size);
        while (this->nodes[now].nxt[val] == -1)
            now = this->nodes[now].nxt[FAIL];
        now = this->nodes[now].nxt[val];
        return;
    }
    using trie<char_size + 1, margin>::trie;
    using trie<char_size + 1, margin>::nodes;

   public:
    void build() {
        correct.resize(this->size());
        for (int i = 0; i < this->size(); ++i) {
            correct[i] = int(this->nodes[i].accept.size());
        }
        std::queue<int> que;
        for (int i = 0; i <= char_size; ++i) {
            if (this->nodes[0].nxt[i] != -1) {
                this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
                que.push(this->nodes[0].nxt[i]);
            } else {
                this->nodes[0].nxt[i] = 0;
            }
        }
        while (!que.empty()) {
            int idx = que.front();
            que.pop();
            auto &now = this->nodes[idx];
            correct[idx] += correct[now.nxt[FAIL]];
            for (int i = 0; i < char_size; ++i) {
                if (now.nxt[i] == -1) continue;
                int fail = now.nxt[FAIL];
                while (this->nodes[fail].nxt[i] == -1)
                    fail = this->nodes[fail].nxt[FAIL];
                this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
                std::vector<int> &u = this->nodes[now.nxt[i]].accept;
                std::vector<int> &v =
                    this->nodes[this->nodes[fail].nxt[i]].accept;
                std::vector<int> accept;
                std::set_union(u.begin(), u.end(), v.begin(), v.end(),
                               std::back_inserter(accept));
                u = accept;
                que.push(now.nxt[i]);
            }
        }
    }

    std::map<int, int> match(const std::string &str, int now = 0) {
        std::map<int, int> map;
        for (const auto &c : str) {
            move_nxt(now, c - margin);
            for (const auto &a : this->nodes[now].accept) {
                map[a]++;
            }
        }
        return map;
    }

    template <class F>
    void query(const std::string &str, F func, int now = 0) {
        for (int i = 0; i < int(str.size()); ++i) {
            move_nxt(now, str[i] - margin);
            for (const auto &a : this->nodes[now].accept) {
                func(a, i);
            }
        }
        return;
    }

    std::pair<int, int> move(const char &c, int now) {
        int sum = 0;
        move_nxt(now, c - margin);
        sum += correct[now];
        return {sum, now};
    }

   private:
    const int FAIL = char_size;
    std::vector<int> correct;
};

}  // namespace ebi

namespace ebi {

void main_() {
    std::string s;
    std::cin >> s;
    int n;
    std::cin >> n;
    std::vector<std::string> ps(n);
    aho_corasick<26, 'a'> ac;
    rep(i, 0, n) {
        std::cin >> ps[i];
        ac.add(ps[i]);
    }
    ac.build();
    std::vector table(s.size(), std::vector<int>());
    ac.query(s, [&](int a, int idx) -> void {
        table[idx].emplace_back(idx - ps[a].size() + 1);
    });
    int ret = -1;
    int sz = s.size();
    int ans = 0;
    rep(i, 0, sz) {
        for (auto l : table[i]) {
            if (l <= ret) continue;
            ret = i;
            ans++;
        }
    }
    std::cout << ans << '\n';
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 207244
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(),(v).end()
#define REP(i,n) for(int i=0,i_len=n; i<i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct LazySegmentTree {
  private:
    int _n, size, log;
    vector<S> dat;
    vector<F> lz;
    void update(int k) { dat[k] = op(dat[2 * k], dat[2 * k + 1]); }
    void all_apply(int k, F f) {
        dat[k] = mapping(f, dat[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
    int lower_bits(int x, int k) { return x & ((1 << k) - 1); }

  public:
    LazySegmentTree() : LazySegmentTree(0) {}
    LazySegmentTree(int n) : LazySegmentTree(vector<S>(n, e())) {}
    LazySegmentTree(const vector<S>& v) : _n(int(v.size())) {
        log = 0;
        while ((1 << log) < _n) log++;
        size = 1 << log;
        dat = vector<S>(2 * size, e());
        lz = vector<F>(size, id());
        for (int i = 0; i < _n; i++) dat[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) update(i);
    }
    // a[p] = x
    void set(int p, S x) {
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        dat[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    // return a[p]
    S get(int p) {
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return dat[p];
    }
    // return op(a[l], ..., a[r-1])
    S prod(int l, int r) {
        if (l == r) return e();
        l += size;
        r += size;
        for (int i = log; i >= 1; i--) {
            if (lower_bits(l, i) > 0) push(l >> i);
            if (lower_bits(r, i) > 0) push((r - 1) >> i);
        }
        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, dat[l++]);
            if (r & 1) smr = op(dat[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }
    S all_prod() { return dat[1]; }
    // a[p] = f(a[p])
    void apply(int p, F f) {
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        dat[p] = mapping(f, dat[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    // i = l...r-1 について a[i] = f(a[i])
    void apply(int l, int r, F f) {
        if (l == r) return;
        l += size;
        r += size;
        for (int i = log; i >= 1; i--) {
            if (lower_bits(l, i) > 0) push(l >> i);
            if (lower_bits(r, i) > 0) push((r - 1) >> i);
        }
        int l2 = l, r2 = r;
        while (l < r) {
            if (l & 1) all_apply(l++, f);
            if (r & 1) all_apply(--r, f);
            l >>= 1;
            r >>= 1;
        }
        l = l2;
        r = r2;
        for (int i = 1; i <= log; i++) {
            if (lower_bits(l, i) > 0) update(l >> i);
            if (lower_bits(r, i) > 0) update((r - 1) >> i);
        }
    }
};

int op(int a, int b){return min(a,b);}
int e(){return 1<<30;}
int mapping(int x, int a){return min(x,a);}
int composition(int x, int y){return min(x,y);}
int id(){return 1<<30;}

vector<int> suffix_array(const string& str) {
    int n = str.size();
    vector<int> sa(n + 1), rank(n + 1, -1);  // sa[i] = 辞書順でi番目であるsuffixの開始位置
    iota(sa.begin(), sa.end(), 0);
    for (int i = 0; i < n; i++) rank[i] = str[i];
    int k;
    auto comp = [&](const int& i, const int& j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return ri < rj;
        }
    };
    for (k = 1; k <= n; k <<= 1) {
        sort(sa.begin(), sa.end(), comp);
        vector<int> tmp(n + 1, 0);
        for (int i = 0; i < n; i++) {
            tmp[sa[i + 1]] = tmp[sa[i]];
            if (comp(sa[i], sa[i + 1])) tmp[sa[i + 1]]++;
        }
        rank = tmp;
    }
    return sa;
}

int find_right(const string& s, const string& t, vector<int>& sa) {
    int l = 0, r = int(s.size())+1;
    while (r - l > 1) {
        int mid = (l + r) / 2;
        if (s.substr(sa[mid], t.size()) <= t) {
            l = mid;
        } else {
            r = mid;
        }
    }
    if (s.substr(sa[l], t.size()) == t){
        return l;
    }else{
        return -1;
    }
}

int find_left(const string& s, const string& t, vector<int>& sa) {
    int l = 0, r = int(s.size());
    while (r - l > 1) {
        int mid = (l + r) / 2;
        if (s.substr(sa[mid], t.size()) < t) {
            l = mid;
        } else {
            r = mid;
        }
    }
    if (s.substr(sa[r], t.size()) == t){
        return r;
    }else{
        return -1;
    }
}


int solve(){
    string s;
    cin >> s;
    vector<int> sa = suffix_array(s);
    LazySegmentTree<int, op, e, int, mapping, composition, id> seg(sa.size());
    int n;
    cin >> n;
    for(int i=0;i<n;i++){
        string p;
        cin >> p;
        int l = find_left(s, p, sa);
        int r = find_right(s, p, sa);
        if(l == -1 || r == -1) continue;
        seg.apply(l, r+1, p.size());
    }
    int ans = 0;
    vector<int> a(s.size(), e());
    for(int i=1;i<sa.size();i++){
        int len = seg.get(i);
        a[sa[i]] = len;
    }

    for(int i=0,j=e();i<s.size();i++){
        chmin(j, i+a[i]);
        if(i+1==j){
            ans++;
            j=e();
        }
    }
    cout << ans << endl;
    return 0;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // int T; cin >> T; REP(t,T) solve();
    // while(!solve());
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 5540
final_rank: 1

code_snippet: /*#include <bits/stdc++.h>
using namespace std;

class rollinghash{*/
    /*
    Copyright (c) 2021 0214sh7
    https://github.com/0214sh7/library/
    */
    /*private:
    const long long mod = (1LL << 61)-1;
    std::vector<long long> Base = {12345,10000000};
    std::vector<long long> BaseInv;
    std::vector<std::vector<long long>> BaseInvExp;
    const long long h = 100;
    
    long long product(long long a,long long b){
        const long long m = 1LL << 31;
        long long a1 = a/m,a2 = a%m;
        long long b1 = b/m,b2 = b%m;
        
        long long r = 0 , s;
        r = (r + 2*a1*b1) % mod;
        s = (a1*b2 + b1*a2) % mod;
        long long s1 = s/m,s2 = s%m;
        s = (2*s1+m*s2) % mod;
        r = (r + s) % mod;
        r = (r + a2*b2) % mod;
        
        return r;
    }
    
    long long power(long long b,long long e){
        long long r=1;
        while(e){
            if(e&1){
                r=product(r,b)%mod;
            }
                b=product(b,b)%mod;
                e >>=1;
        }
        return r;
    }
    
    public:
    std::string S;
    std::vector<std::vector<long long>> H,Hsum;
    
    void init(std::string cs){
        S=cs;
        int n=S.size();
        
        BaseInv.resize(Base.size());
        BaseInvExp.resize(Base.size());
        H.resize(Base.size());
        Hsum.resize(Base.size());
        for(int i=0;i<Base.size();i++){
            BaseInvExp[i].assign(n+1,1);
            H[i].assign(n+1,0);
            Hsum[i].assign(n+1,0);
        }
        
        //逆元
        for(int i=0;i<Base.size();i++){
            BaseInv[i]=power(Base[i],mod-2);
        }
        for(int i=0;i<Base.size();i++){
            for(int j=0;j<n;j++){
                BaseInvExp[i][j+1] = product(BaseInvExp[i][j],BaseInv[i]);
            }
        }
        
        //本体
        for(int i=0;i<Base.size();i++){
            long long b=1;
            for(int j=0;j<n;j++){
                H[i][j]=product(b,S[j]+h);
                b=product(b,Base[i]);
            }
        }
        
        //累積和
        for(int i=0;i<Base.size();i++){
            for(int j=0;j<n;j++){
                Hsum[i][j+1]=(Hsum[i][j]+H[i][j])%mod;
            }
        }
    }
    
    rollinghash(std::string S){
        init(S);
    }
    
    std::vector<long long> get(int l,int r){
        std::vector<long long> R;
        for(int i=0;i<Base.size();i++){
            long long g = (Hsum[i][r]-Hsum[i][l]+mod)%mod;
            g=product(g,BaseInvExp[i][l]);
            R.push_back(g);
        }
        return R;
    }
    
    std::vector<long long> instant(string T){
        std::vector<long long> R;
        for(int i=0;i<Base.size();i++){
            long long r = 0, b = 1;
            for(int j=0;j<T.size();j++){
                r = (r+product(b,T[j]+h))%mod;
                b = product(b,Base[i]);
            }
            R.push_back(r);
        }
        return R;
    }
    
};

signed main() {
    int N,M;
    string S,Q;
    cin >> N >> M;
    cin >> S;
    int l=0,r=1;
    set<vector<long long>> R;
    rollinghash roliha(S);
    
    for(int i=0;i<M;i++){
        cin >> Q;
        if(Q=="L++"){l++;}
        else if(Q=="L--"){l--;}
        else if(Q=="R++"){r++;}
        else{r--;}
        vector<long long> K = roliha.get(l,r);
        R.insert(K);
        
    }
    cout << R.size() << endl;
    return 0;
}*/

/*int main() {
    
    rollinghash rolihash("abcab");
    
    std::cout << "\"abcab\"の[0,2)文字目、つまり\"ab\"のハッシュ値" << std::endl;
    std::vector<long long> a = rolihash.get(0,2);
    for(int i=0;i<a.size();i++){
        std::cout << a[i] << " ";
    }
    std::cout << std::endl << std::endl;
    
    std::cout << "\"abcab\"の[1,4)文字目、つまり\"bca\"のハッシュ値" << std::endl;
    std::vector<long long> b = rolihash.get(1,4);
    for(int i=0;i<b.size();i++){
        std::cout << b[i] << " ";
    }
    std::cout << std::endl << std::endl;
    
    std::cout << "\"abcab\"の[3,5)文字目、つまり\"ab\"のハッシュ値" << std::endl;
    std::vector<long long> c = rolihash.get(3,5);
    for(int i=0;i<c.size();i++){
        std::cout << c[i] << " ";
    }
    std::cout << std::endl << std::endl;
    
    std::cout << "\"bca\"のハッシュ値" << std::endl;
    std::vector<long long> d = rolihash.instant("bca");
    for(int i=0;i<d.size();i++){
        std::cout << d[i] << " ";
    }
    std::cout << std::endl << std::endl;
    
    return 0;
}*/

#include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>
#include <chrono>
#include <random>
#include <memory>
 
/* macro */
 
#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i< (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n-i64(1))); i>=(i64)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
 
/* macro end */
 
/* template */
 
namespace ebi {
 
#ifdef LOCAL
#define debug(...)                                                    \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
 
void debug_out() { std::cerr << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}
 
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, std::pair<T1, T2> pa) {
    return os << pa.first << " " << pa.second;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}
 
using size_t = std::size_t;
using i64 = long long;
using u64 = unsigned long long;
 
template<class T> void fill(std::vector<T> &v) { for(T &e: v) std::cin >> e; }
 
template<class T>
struct Edge {
    int to;
    T cost;
    Edge(int to, T cost) : to(to), cost(cost) { }
};
 
template<class T>
using Graph = std::vector<std::vector<Edge<T>>>;
 
using graph = std::vector<std::vector<int>>;
 
template <class T>
inline bool chmin(T &a, T b) {
    if (a > b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
T gcd(T a, T b){
    if( b==0 ) return a;
    else return gcd(b, a%b);
}
 
template <class T>
T lcm(T a, T b) {
    return (a*b)/gcd(a,b);
}
 
template<class T>
T Pow(T x, i64 n) {
    T res = 1;
    while(n>0){
        if(n&1) res = res *x;
        x = x*x;
        n>>=1;
    }
    return res;
}
 
template<class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}
 
constexpr i64 LNF = std::numeric_limits<i64>::max()/4;
 
constexpr int INF = std::numeric_limits<int>::max()/4;
 
const long double PI = acos(-1);
 
const std::vector<int> dy = {1,0,-1,0,1,1,-1,-1};
const std::vector<int> dx = {0,1,0,-1,1,-1,1,-1};
 
}
 
/* template end */

/*
    author: noshi91
    reference: https://noshi91.hatenablog.com/entry/2019/03/31/174006
    noshi91のブログで公開されているmodintを元にinv(), pow()を追加したものです
*/

#include <cstdint>
#include <iostream>

namespace ebi {

template<std::uint_fast64_t Modulus>
class modint {
  using u64 = std::uint_fast64_t;

public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr u64 &val() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
        a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
        if (exp % 2) {
            *this *= rhs;
        }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }
    constexpr modint operator-() const { return modint() - *this; }
    bool operator==(const u64 rhs) {
        return a == rhs;
    }
    bool operator!=(const u64 rhs) {
        return a != rhs;
    }
    constexpr modint& operator++() {
        a++;
        if( a == mod() ) a = 0;
        return *this;
    }
    constexpr modint& operator--() {
        if( a == 0 ) a = mod();
        a--;
        return *this;
    }

    modint pow(u64 n) const noexcept {
        modint res = 1;
        modint x = a;
        while(n>0){
            if(n&1) res *= x;
            x *= x;
            n >>=1;
        }
        return res;
    }
    modint inv() const {
        return pow(Modulus-2);
    }

    static u64 mod() {
        return Modulus;
    }
};

using modint998244353 = modint<998244353>;
using modint1000000007 = modint<1000000007>;

template<std::uint_fast64_t Modulus>
std::ostream& operator<<(std::ostream& os, modint<Modulus> a){
    return os << a.val();
}

} // namespace ebi

namespace x0214sh7 {

class rollinghash{
    /*
    Copyright (c) 2021 0214sh7
    https://github.com/0214sh7/library/
    */
    private:
    const long long mod = (1LL << 61)-1;
    std::vector<long long> Base = {12345,10000000};
    std::vector<long long> BaseInv;
    std::vector<std::vector<long long>> BaseInvExp;
    const long long h = 100;
    
    long long product(long long a,long long b){
        const long long m = 1LL << 31;
        long long a1 = a/m,a2 = a%m;
        long long b1 = b/m,b2 = b%m;
        
        long long r = 0 , s;
        r = (r + 2*a1*b1) % mod;
        s = (a1*b2 + b1*a2) % mod;
        long long s1 = s/m,s2 = s%m;
        s = (2*s1+m*s2) % mod;
        r = (r + s) % mod;
        r = (r + a2*b2) % mod;
        
        return r;
    }
    
    long long power(long long b,long long e){
        long long r=1;
        while(e){
            if(e&1){
                r=product(r,b)%mod;
            }
                b=product(b,b)%mod;
                e >>=1;
        }
        return r;
    }
    
    public:
    std::string S;
    std::vector<std::vector<long long>> H,Hsum;
    
    void init(std::string cs){
        S=cs;
        int n=S.size();
        
        BaseInv.resize(Base.size());
        BaseInvExp.resize(Base.size());
        H.resize(Base.size());
        Hsum.resize(Base.size());
        for(int i=0;i<Base.size();i++){
            BaseInvExp[i].assign(n+1,1);
            H[i].assign(n+1,0);
            Hsum[i].assign(n+1,0);
        }
        
        //逆元
        for(int i=0;i<Base.size();i++){
            BaseInv[i]=power(Base[i],mod-2);
        }
        for(int i=0;i<Base.size();i++){
            for(int j=0;j<n;j++){
                BaseInvExp[i][j+1] = product(BaseInvExp[i][j],BaseInv[i]);
            }
        }
        
        //本体
        for(int i=0;i<Base.size();i++){
            long long b=1;
            for(int j=0;j<n;j++){
                H[i][j]=product(b,S[j]+h);
                b=product(b,Base[i]);
            }
        }
        
        //累積和
        for(int i=0;i<Base.size();i++){
            for(int j=0;j<n;j++){
                Hsum[i][j+1]=(Hsum[i][j]+H[i][j])%mod;
            }
        }
    }
    
    rollinghash(std::string S){
        init(S);
    }
    
    std::vector<long long> get(int l,int r){
        std::vector<long long> R;
        for(int i=0;i<Base.size();i++){
            long long g = (Hsum[i][r]-Hsum[i][l]+mod)%mod;
            g=product(g,BaseInvExp[i][l]);
            R.push_back(g);
        }
        return R;
    }
    
    std::vector<long long> instant(std::string P){
        std::vector<long long> R;
        for(int i=0;i<Base.size();i++){
            long long r = 0, b = 1;
            for(int j=0;j<P.size();j++){
                r = (r+product(b,P[j]+h))%mod;
                b = product(b,Base[i]);
            }
            R.push_back(r);
        }
        return R;
    }
    
};

}


namespace ebi {

using mint = modint998244353;

using ld = long double;

using P = std::pair<int,int>;

void main_() {
    std::string s;
    std::cin >> s;
    const int m = s.size();
    int n;
    std::cin >> n;
    std::vector<std::string> p(n);
    int max = 0;
    rep(i,0,n) {
        std::cin >> p[i];
        chmax(max, int(p[i].size()));
    }
    std::vector<std::map<std::pair<long long, long long>,int>> map(max+1);
    x0214sh7::rollinghash hash(s);
    rep(i,0,n) {
        auto h = hash.instant(p[i]);
        map[p[i].size()][{h[0], h[1]}] = 1;
    }
    std::vector<int> seg(m, INF);
    i64 x = 0;
    rep(i,1,max+1) {
        if(int(map[i].size()) == 0) continue;
        rep(j,0,m-i+1) {
            if(seg[j] < INF) continue;
            x++;
            auto h = hash.get(j, j+i);
            if(map[i].find({h[0], h[1]}) != map[i].end()) {
                chmin(seg[j], j+i);
            }
        }
    }
    int r = INF;
    int ans = 0;
    rep(i,0,m) {
        if(seg[i] == INF) continue;
        if(r <= i) {
            ans++;
            r = seg[i];
        }
        else {
            chmin(r, seg[i]);
        }
    }
    if(r < INF) ans++;
    std::cout << ans << std::endl;
}
 
}

 
int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    while(t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 9804
final_rank: 10

code_snippet: #line 1 "a.cpp"
#include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>
#include <chrono>
#include <random>
#include <memory>
 
/* macro */
 
#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i< (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n-i64(1))); i>=(i64)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define Bit(n) (1LL<<(n))
 
/* macro end */
 
/* template */
 
namespace ebi {
 
#ifdef LOCAL
#define debug(...)                                                    \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
 
void debug_out() { std::cerr << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}
 
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, std::pair<T1, T2> pa) {
    return os << pa.first << " " << pa.second;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}
 
using size_t = std::size_t;
using i64 = long long;
using u64 = unsigned long long;
 
template<class T> void fill(std::vector<T> &v) { for(T &e: v) std::cin >> e; }
 
template <class T>
inline bool chmin(T &a, T b) {
    if (a > b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
T gcd(T a, T b){
    if( b==0 ) return a;
    else return gcd(b, a%b);
}
 
template <class T>
T lcm(T a, T b) {
    return (a*b)/gcd(a,b);
}
 
template<class T>
T Pow(T x, i64 n) {
    T res = 1;
    while(n>0){
        if(n&1) res = res *x;
        x = x*x;
        n>>=1;
    }
    return res;
}
 
template<class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}
 
constexpr i64 LNF = std::numeric_limits<i64>::max()/4;
 
constexpr int INF = std::numeric_limits<int>::max()/4;
 
const long double PI = acos(-1);
 
const std::vector<int> dy = {1,0,-1,0,1,1,-1,-1};
const std::vector<int> dx = {0,1,0,-1,1,-1,1,-1};
 
}
 
/* template end */

#line 2 "String/trie.hpp"

#line 5 "String/trie.hpp"

namespace ebi {

namespace internal {

template<int char_size>
struct trie_node {
    int common;
    int nxt[char_size];
    std::vector<int> accept;
    trie_node() : common(0) {
        memset(nxt, -1, sizeof(nxt));
    }
};

}

template<int char_size, int margin>
struct trie {
public:
    trie() {
        nodes.emplace_back(Node());
    }

    void add(const std::string &str) {
        int idx = 0;
        for(const auto &c: str) {
            int val = c - margin;
            assert(0 <= val && val < char_size);
            if(nodes[idx].nxt[val] < 0) {
                nodes[idx].nxt[val] = int(nodes.size());
                nodes.emplace_back(Node());
            }
            idx = nodes[idx].nxt[val];
            nodes[idx].common++;
        }
        nodes[idx].accept.emplace_back(nodes[0].common++);
    }

    template<class F>
    void query(const std::string &str, int start, F func) const {
        int idx = 0;
        for(int i = start; i < int(str.size()); ++i) {
            int val = str[i] - margin;
            assert(0 <= val && val < char_size);
            int nxt = nodes[idx].nxt[val];
            if(nxt < 0) {
                return;
            }
            idx = nxt;
            for(const auto id: nodes[idx].accept) {
                func(id);
            }
        }
        return;
    }

    bool search(const std::string &str, int start, bool prefix = false) const {
        int idx = 0;
        for(int i = start; i < int(str.size()); ++i) {
            int val = str[i] - margin;
            assert(0 <= val && val < char_size);
            int nxt = nodes[idx].nxt[val];
            if(nxt < 0) {
                return -1;
            }
            idx = nxt;
        }
        return prefix ? true : (nodes[idx].accept.size() > 0);
    }

    int size() const {
        return int(nodes.size());
    }
private:
    using Node = internal::trie_node<char_size>;
protected:
    std::vector<Node> nodes;
};

}
#line 136 "a.cpp"

namespace ebi {

template<int char_size, int margin>
struct aho_corasick : trie<char_size+1, margin> {
private:
    void move_nxt(int &now, int val) {
        assert(0 <= val && val < char_size);
        while(this->nodes[now].nxt[val] == -1) now = this->nodes[now].nxt[FAIL];
        now = this->nodes[now].nxt[val];
        return;
    }
    using trie<char_size + 1, margin>::trie;
    using trie<char_size + 1, margin>::nodes;

public:

    void build() {
        correct.resize(this->size());
        for(int i = 0; i < this->size(); ++i) {
            correct[i] = int(this->nodes[i].accept.size());
        }
        std::queue<int> que;
        for(int i = 0; i <= char_size; ++i) {
            if(this->nodes[0].nxt[i] != -1) {
                this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
                que.push(this->nodes[0].nxt[i]);
            } else {
                this->nodes[0].nxt[i] = 0;
            }
        }
        while(!que.empty()) {
            int idx = que.front();
            que.pop();
            auto &now = this->nodes[idx];
            correct[idx] += correct[now.nxt[FAIL]];
            for(int i = 0; i < char_size; ++i) {
                if(now.nxt[i] == -1) continue;
                int fail = now.nxt[FAIL];
                while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
                this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
                std::vector<int> &u = this->nodes[now.nxt[i]].accept;
                std::vector<int> &v = this->nodes[this->nodes[fail].nxt[i]].accept;
                std::vector<int> accept;
                std::set_union(u.begin(), u.end(), v.begin(), v.end(), std::back_inserter(accept));
                u = accept;
                que.push(now.nxt[i]);
            }
        }
    }

    std::map<int, int> match(const std::string &str, int now = 0) {
        std::map<int, int> map;
        for(const auto &c: str) {
            move_nxt(now, c - margin);
            for(const auto &a: this->nodes[now].accept) {
                map[a]++;
            }
        }
        return map;
    }

    std::pair<int,int> move(const char &c, int now) {
        int sum = 0;
        move_nxt(now, c - margin);
        sum += correct[now];
        return {sum, now};
    }
private:
    const int FAIL = char_size;
    std::vector<int> correct;
};

}

namespace ebi {

using ld = long double;

void main_() {
    std::string s;
    int n;
    std::cin >> s >> n;
    aho_corasick<26, 'a'> ac;
    rep(i,0,n) {
        std::string p;
        std::cin >> p;
        ac.add(p);
    }
    ac.build();
    int now = 0;
    int ans = 0;
    for(auto c: s) {
        auto [x, y] = ac.move(c, now);
        if(x > 0) {
            ans++;
            now = 0;
        }
        else {
            now = y;
        }
    }
    std::cout << ans << '\n';
}
 
}

 
int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    while(t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 22348
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 1000005
#define MAX 26

enum Type{
	UNDEFINED,
	EXIST,
	NOT,
};

struct Node{
	int parent_id,children[MAX],suffix_link;
	bool finish_FLG;
};

struct Info{
    Info(int arg_node_id,int arg_ch){
        node_id = arg_node_id;
        ch = arg_ch;
    }

    int node_id,ch;
};

int IND = 1;
Node nodes[SIZE];
Type memo[SIZE];
char buf[SIZE];
string P[SIZE];


int main(){

	//★ルートの情報を設定★
	int root = 0;
	nodes[root].suffix_link = -1;

	//トライ木のノードを初期化
	for(int i = 0; i < SIZE; i++){
		nodes[i].parent_id = -1;
		nodes[i].finish_FLG = false;
		for(int k = 0; k < MAX; k++){
			nodes[i].children[k] = -1;
		}
	}

	scanf("%s",buf);
	int N;
	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		cin >> P[i];

		int tmp_ch,tmp_loc,parent_id,tmp_index;

		//トライ木を構成する
		tmp_index = 0;
		tmp_ch = P[i][tmp_index]-'a';

		tmp_loc = root;
		tmp_index = 0;

		while(true){

			parent_id = tmp_loc;

			if(nodes[tmp_loc].children[tmp_ch] == -1){

				nodes[tmp_loc].children[tmp_ch] = IND++;
			}
			//子ノードに移動
			tmp_loc = nodes[tmp_loc].children[tmp_ch];
			nodes[tmp_loc].parent_id = parent_id;

			tmp_index++;

			if(tmp_index == P[i].length()){ //今回の数字が最後の文字だった場合
				nodes[tmp_loc].finish_FLG = true;
				break;
			}
			tmp_ch = P[i][tmp_index]-'a';
		}

	}

	//Suffix_linkを構築する
	int node_id;
	queue<Info> MAKE_SL;
	for(int i = 0; i < MAX; i++){
		if(nodes[root].children[i] != -1){
			node_id = nodes[root].children[i];
			nodes[node_id].suffix_link = root; //★root直下のsuffix_linkは必ずrootなので、queueには突っ込まない★
			for(int k = 0; k < MAX; k++){
				if(nodes[node_id].children[k] != -1){
					MAKE_SL.push(Info(nodes[node_id].children[k],k)); //ノードのidと、最後の経路をpushする
				}
			}
		}
	}

	int tmp_ch,tmp_loc;

	while(!MAKE_SL.empty()){
		node_id = MAKE_SL.front().node_id; //★新たにsuffix_linkを張りたいノードのid★
		tmp_ch = MAKE_SL.front().ch;
		MAKE_SL.pop();

		for(int i = 0; i < MAX; i++){
			if(nodes[node_id].children[i] != -1){
				MAKE_SL.push(Info(nodes[node_id].children[i],i));
			}
		}

		//★親のsuffix_link先は、自分のsuffix_link先のpre_fixになっているので、親のsuffix_link情報を利用する★

		//tmp_chへ下ることのできる、親からのsuffix_link先のノードを探す
		for(tmp_loc = nodes[nodes[node_id].parent_id].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
			if(nodes[tmp_loc].children[tmp_ch] != -1){
				break;
			}
		}

		if(tmp_loc == root){
			if(nodes[root].children[tmp_ch] != -1){
				nodes[node_id].suffix_link = nodes[root].children[tmp_ch];
			}else{
				nodes[node_id].suffix_link = root;
			}
		}else{
			nodes[node_id].suffix_link = nodes[tmp_loc].children[tmp_ch];
		}
	}

	//suffix_link上にfinish_FLG = trueのノードがあるか前計算する
	memo[root] = NOT;
	for(int i = 1; i < IND; i++){

		memo[i] = UNDEFINED;
	}

	queue<int> Q;

	for(int i = 0; i < MAX; i++){

		if(nodes[root].children[i] == -1)continue;

		Q.push(nodes[root].children[i]);
	}

	while(!Q.empty()){

		int node = Q.front();
		Q.pop();

		for(int i = 0; i < MAX; i++){

			if(nodes[node].children[i] == -1)continue;

			Q.push(nodes[node].children[i]);
		}

		if(nodes[node].finish_FLG||memo[nodes[node].suffix_link] == EXIST){

			memo[node] = EXIST;
		}else{

			memo[node] = NOT;
		}
	}


	//T上の文字を走査する
	tmp_loc = root;
	int ans = 0;

	for(int i = 0; buf[i] != '\0'; i++){
		tmp_ch = buf[i]-'a';

		if(nodes[tmp_loc].children[tmp_ch] != -1){ //次の文字が繋がる場合
			tmp_loc = nodes[tmp_loc].children[tmp_ch]; //次のノードに移動する

			if(memo[tmp_loc] == EXIST){

				ans++;
				tmp_loc = root;
			}

		}else{ //次の文字と一致しない場合→suffix_linkを辿る

			if(tmp_loc == root)continue;

			for(tmp_loc = nodes[tmp_loc].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
				if(nodes[tmp_loc].children[tmp_ch] != -1){
					break;
				}
			}
			if(nodes[tmp_loc].children[tmp_ch] != -1){ //tmp_chへと繋がるノードに辿り着いた場合
				tmp_loc = nodes[tmp_loc].children[tmp_ch];


				if(memo[tmp_loc] == EXIST){

					ans++;
					tmp_loc = root;
				}
			}else{
				//Do nothing (tmp_loc == rootであるはず)
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 151068
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005
#define MAX 26

struct Node{
	int parent_id,children[MAX],suffix_link;
	bool finish_FLG;
};

enum Type{
    Unknown,
    TRUE,
    FALSE,
};


struct Info{
    Info(int arg_node_id,int arg_ch){
        node_id = arg_node_id;
        ch = arg_ch;
    }

    int node_id,ch;
};

int IND = 1;
char buf[SIZE];
string P[SIZE];
Node nodes[SIZE];
Type memo[SIZE];

int main(){

	//★ルートの情報を設定★
	int root = 0;
	nodes[root].suffix_link = -1;

	//トライ木のノードを初期化
	for(int i = 0; i < SIZE; i++){
		nodes[i].parent_id = -1;
		nodes[i].finish_FLG = false;
		for(int k = 0; k < MAX; k++){
			nodes[i].children[k] = -1;
		}
	}

	scanf("%s",buf);


	int N;
	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		cin >> P[i];
		int len_P = P[i].length();

		int tmp_ch,tmp_loc,parent_id,tmp_index;

		//トライ木を構成する
		tmp_index = 0; //rootが出発点
		tmp_ch = P[i][tmp_index]-'a';

		tmp_loc = root;
		tmp_index = 0; //Pの何文字目か

		while(true){

			parent_id = tmp_loc;

			if(nodes[tmp_loc].children[tmp_ch] == -1){

				nodes[tmp_loc].children[tmp_ch] = IND++; //新しいノードへ移動する場合
			}

			//子ノードに移動
			tmp_loc = nodes[tmp_loc].children[tmp_ch];
			nodes[tmp_loc].parent_id = parent_id;

			tmp_index++;

			if(tmp_index == len_P){ //今回の数字が最後の文字だった場合
				nodes[tmp_loc].finish_FLG = true;
				break;
			}
			tmp_ch = P[i][tmp_index]-'a';
		}
	}



	//Suffix_linkを構築する
	int node_id;
	queue<Info> MAKE_SL;
	for(int i = 0; i < MAX; i++){
		if(nodes[root].children[i] != -1){ //i方向に個あり
			node_id = nodes[root].children[i];
			nodes[node_id].suffix_link = root; //★root直下のsuffix_linkは必ずrootなので、queueには突っ込まない★
			for(int k = 0; k < MAX; k++){
				if(nodes[node_id].children[k] != -1){
					MAKE_SL.push(Info(nodes[node_id].children[k],k)); //ノードのidと、最後の経路をpushする
				}
			}
		}
	}

	int tmp_loc;

	while(!MAKE_SL.empty()){
		node_id = MAKE_SL.front().node_id; //★新たにsuffix_linkを張りたいノードのid★
		int tmp_ch = MAKE_SL.front().ch; //新たにsuffix_linkを張りたいノードの末尾の文字
		MAKE_SL.pop();

		for(int i = 0; i < MAX; i++){
			if(nodes[node_id].children[i] != -1){
				MAKE_SL.push(Info(nodes[node_id].children[i],i));
			}
		}

		/*親のsuffix_link先は、自分のsuffix_link先のpre_fixになっているので、親のsuffix_link情報を利用する
		 * 親:abcd→sufix_linkの例: bcd
		 * 自分:abcde→suffix_linkの例:bcde
		 *
		 *
		 * */

		//tmp_chへ下ることのできる、親からのsuffix_link先のノードを探す
		for(tmp_loc = nodes[nodes[node_id].parent_id].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
			if(nodes[tmp_loc].children[tmp_ch] != -1){
				break;
			}
		}

		if(tmp_loc == root){
			if(nodes[root].children[tmp_ch] != -1){
				nodes[node_id].suffix_link = nodes[root].children[tmp_ch];
			}else{
				nodes[node_id].suffix_link = root;
			}
		}else{
			nodes[node_id].suffix_link = nodes[tmp_loc].children[tmp_ch];
		}
	}

	//suffix_linkを辿り、finish_flgがtrueのものに出くわすか調べる
	for(int i = 0; i < IND; i++){
		memo[i] = Unknown;
	}

	queue<int> Q;
	for(int i = 0; i < MAX; i++){
		if(nodes[root].children[i] != -1){
			Q.push(nodes[root].children[i]);
		}
	}

	//ノードに近いものから調べる
	while(!Q.empty()){
		tmp_loc = Q.front();
		Q.pop();
		for(int i = 0; i < MAX; i++){
			if(nodes[tmp_loc].children[i] != -1){
				Q.push(nodes[tmp_loc].children[i]);
			}
		}

		if(nodes[tmp_loc].finish_FLG){
			memo[tmp_loc] = TRUE;
		}else{
			for(int k = nodes[tmp_loc].suffix_link; k != root; k = nodes[k].suffix_link){
				if(memo[k] != Unknown){
					memo[tmp_loc] = memo[k];
					break;
				}
				if(nodes[k].finish_FLG){
					memo[tmp_loc] = TRUE;
					break;
				}
			}
			if(memo[tmp_loc] == Unknown){
				memo[tmp_loc] = FALSE;
			}
		}
	}


	tmp_loc = root;
	int ans = 0;


	for(int i = 0; buf[i] != '\0'; i++){
		int tmp_ch = buf[i]-'a';

		if(nodes[tmp_loc].children[tmp_ch] != -1){ //tmp_locから次に行ける場合
			tmp_loc = nodes[tmp_loc].children[tmp_ch];

			if(memo[tmp_loc] == TRUE){
				ans++;
				tmp_loc = root;
			}else{
				//Do nothing
			}

		}else{ //tmp_locから次へ行けない場合

			if(tmp_loc == root)continue; //rootの場合はSKIP

			//suffix_linkを辿り、tmp_chへ移れるノードがあるか調べる
			for(tmp_loc = nodes[tmp_loc].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
				if(nodes[tmp_loc].children[tmp_ch] != -1)break;
			}

			if(tmp_loc == root){ //rootまで戻った場合
				if(nodes[tmp_loc].children[tmp_ch] != -1){ //rootの子にtmp_chがいる場合
					tmp_loc = nodes[tmp_loc].children[tmp_ch];
					if(nodes[tmp_loc].finish_FLG){
						ans++;
						tmp_loc = root;
					}
				}else{
					//Do nothing
				}
			}else{ //途中でtmp_chへ移れるノードが見つかった場合
				tmp_loc = nodes[tmp_loc].children[tmp_ch];

				if(memo[tmp_loc] == TRUE){
					ans++;
					tmp_loc = root;
				}else{
					//Do nothing
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 16504
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005
#define MAX 26

struct Node{
	int parent_id,children[MAX],suffix_link;
	bool finish_FLG;
};

struct Info{
    Info(int arg_node_id,int arg_ch){
        node_id = arg_node_id;
        ch = arg_ch;
    }

    int node_id,ch;
};

int IND = 1;
char buf[SIZE];
string P[SIZE];
Node nodes[SIZE];

int main(){

	//★ルートの情報を設定★
	int root = 0;
	nodes[root].suffix_link = -1;

	//トライ木のノードを初期化
	for(int i = 0; i < SIZE; i++){
		nodes[i].parent_id = -1;
		nodes[i].finish_FLG = false;
		for(int k = 0; k < MAX; k++){
			nodes[i].children[k] = -1;
		}
	}

	scanf("%s",buf);


	int N;
	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		cin >> P[i];
		int len_P = P[i].length();

		int tmp_ch,tmp_loc,parent_id,tmp_index;

		//トライ木を構成する
		tmp_index = 0; //rootが出発点
		tmp_ch = P[i][tmp_index]-'a';

		tmp_loc = root;
		tmp_index = 0; //Pの何文字目か

		while(true){

			parent_id = tmp_loc;

			if(nodes[tmp_loc].children[tmp_ch] == -1){

				nodes[tmp_loc].children[tmp_ch] = IND++; //新しいノードへ移動する場合
			}

			//子ノードに移動
			tmp_loc = nodes[tmp_loc].children[tmp_ch];
			nodes[tmp_loc].parent_id = parent_id;

			tmp_index++;

			if(tmp_index == len_P){ //今回の数字が最後の文字だった場合
				nodes[tmp_loc].finish_FLG = true;
				break;
			}
			tmp_ch = P[i][tmp_index]-'a';
		}
	}



	//Suffix_linkを構築する
	int node_id;
	queue<Info> MAKE_SL;
	for(int i = 0; i < MAX; i++){
		if(nodes[root].children[i] != -1){ //i方向に個あり
			node_id = nodes[root].children[i];
			nodes[node_id].suffix_link = root; //★root直下のsuffix_linkは必ずrootなので、queueには突っ込まない★
			for(int k = 0; k < MAX; k++){
				if(nodes[node_id].children[k] != -1){
					MAKE_SL.push(Info(nodes[node_id].children[k],k)); //ノードのidと、最後の経路をpushする
				}
			}
		}
	}

	int tmp_loc;

	while(!MAKE_SL.empty()){
		node_id = MAKE_SL.front().node_id; //★新たにsuffix_linkを張りたいノードのid★
		int tmp_ch = MAKE_SL.front().ch; //新たにsuffix_linkを張りたいノードの末尾の文字
		MAKE_SL.pop();

		for(int i = 0; i < MAX; i++){
			if(nodes[node_id].children[i] != -1){
				MAKE_SL.push(Info(nodes[node_id].children[i],i));
			}
		}

		/*親のsuffix_link先は、自分のsuffix_link先のpre_fixになっているので、親のsuffix_link情報を利用する
		 * 親:abcd→sufix_linkの例: bcd
		 * 自分:abcde→suffix_linkの例:bcde
		 *
		 *
		 * */

		//tmp_chへ下ることのできる、親からのsuffix_link先のノードを探す
		for(tmp_loc = nodes[nodes[node_id].parent_id].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
			if(nodes[tmp_loc].children[tmp_ch] != -1){
				break;
			}
		}

		if(tmp_loc == root){
			if(nodes[root].children[tmp_ch] != -1){
				nodes[node_id].suffix_link = nodes[root].children[tmp_ch];
			}else{
				nodes[node_id].suffix_link = root;
			}
		}else{
			nodes[node_id].suffix_link = nodes[tmp_loc].children[tmp_ch];
		}
	}

/*	for(int i = 0; i < IND; i++){

		printf("node[%d].suffix_link;%d\n",i,nodes[i].suffix_link);
	}*/

	tmp_loc = root;
	int ans = 0;


	for(int i = 0; buf[i] != '\0'; i++){
		int tmp_ch = buf[i]-'a';

		if(nodes[tmp_loc].children[tmp_ch] != -1){ //tmp_locから次に行ける場合
			tmp_loc = nodes[tmp_loc].children[tmp_ch];

			//suffix_linkをrootまで辿り、finish_FLGがtrueのノードがないか調べる
			if(nodes[tmp_loc].finish_FLG){ //このノード自体が終了地点
				ans++;
				tmp_loc = root; //'*'出力してrootへ
			}else{
				//suffix_linkをたどる
				for(int k = nodes[tmp_loc].suffix_link; k != root; k = nodes[k].suffix_link){
					if(nodes[k].finish_FLG){
						ans++;
						tmp_loc = root;
						break;
					}
				}
			}
		}else{ //tmp_locから次へ行けない場合

			if(tmp_loc == root)continue; //rootの場合はSKIP

			//suffix_linkを辿り、tmp_chへ移れるノードがあるか調べる
			for(tmp_loc = nodes[tmp_loc].suffix_link; tmp_loc != root; tmp_loc = nodes[tmp_loc].suffix_link){
				if(nodes[tmp_loc].children[tmp_ch] != -1)break;
			}

			if(tmp_loc == root){ //rootまで戻った場合
				if(nodes[tmp_loc].children[tmp_ch] != -1){ //rootの子にtmp_chがいる場合
					tmp_loc = nodes[tmp_loc].children[tmp_ch];
					if(nodes[tmp_loc].finish_FLG){
						ans++;
						tmp_loc = root;
					}
				}else{
					//Do nothing
				}
			}else{ //途中でtmp_chへ移れるノードが見つかった場合
				tmp_loc = nodes[tmp_loc].children[tmp_ch];

				if(nodes[tmp_loc].finish_FLG){
					ans++;
					tmp_loc = root;
				}else{

					//suffix_linkをたどる
					for(int k = nodes[tmp_loc].suffix_link; k != root; k = nodes[k].suffix_link){
						if(nodes[k].finish_FLG){
							ans++;
							tmp_loc = root;
							break;
						}
					}
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 16456
final_rank: 2