結果

問題 No.430 文字列検索
コンテスト
ユーザー mkreem
提出日時 2026-04-01 15:01:36
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 7 ms / 2,000 ms
コード長 36,801 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,835 ms
コンパイル使用メモリ 282,264 KB
実行使用メモリ 286,608 KB
最終ジャッジ日時 2026-04-01 15:01:39
合計ジャッジ時間 2,910 ms
ジャッジサーバーID
(参考情報)
judge2_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 14
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <unordered_map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

template <typename T = int>
struct Graph {
    // 辺の構造体
    struct Edge {
        int from, to;
        T cost;
        int id;

        Edge() : from(-1), to(-1), cost(-1), id(-1) {}
        Edge(int from, int to, T cost = 1, int id = -1) : from(from), to(to), cost(cost), id(id) {}

        bool operator<(const Edge &rhs) const { return cost < rhs.cost; }
        friend std::ostream& operator<<(std::ostream& os, const Edge& e) {
            return os << "(" << e.from << " -> " << e.to << "  weight: " << e.cost << ", id: " << e.id << ")";
        }
    };

    Graph() = default;
    Graph(int N) : N(N), M(0), G(N) {}

private:
    int N, M;
    std::vector<std::vector<Edge>> G;

public:
    bool is_weighted = false;
    void add_edge(const int& u, const int& v, T w = 1) {
        G[u].push_back({u, v, w, M});
        G[v].push_back({v, u, w, M++});
        if (w != 1) {
            is_weighted = true;
        }
    }
    void add_directed_edge(const int& u, const int& v, T w = 1) {
        G[u].push_back({u, v, w, M++});
        if (w != 1) {
            is_weighted = true;
        }
    }
    void read(const int& M, bool weighted = false, bool directed = false, int padding = 1) {
        for (int i = 0; i < M; i++) {
            int u, v; std::cin >> u >> v;
            u -= padding;
            v -= padding;
            T w(1);
            if (weighted) {
                is_weighted = true;
                std::cin >> w;
            }
            if (directed) {
                add_directed_edge(u, v, w);
            } else {
                add_edge(u, v, w);
            }
        }
    }
    int size() const { return N; }
    const std::vector<Edge>& operator[](int v) const { return G[v]; }
    std::vector<Edge>& operator[](int v) { return G[v]; }
    std::vector<Edge> edges() {
        std::vector<Edge> es(M);
        for (int v = 0; v < N; v++) {
            for (const auto& nv : G[v]) {
                es[nv.id] = nv;
            }
        }
        return es;
    }

    // 最短距離 ===========================================
    std::pair<std::vector<T>, std::vector<Edge>> BFS(const int& start) {
        std::vector<T> dist(N, std::numeric_limits<T>::max());
        std::queue<int> q;
        /**
         * @param prev_edges[target] : start から target までの最短経路における、target を訪れる直前に通った辺
         */
        std::vector<Edge> prev_edges(N);
        dist[start] = 0;
        q.push(start);
        while (!q.empty()) {
            int v = q.front(); q.pop();
            for (const auto& e : G[v]) {
                int nv = e.to;
                if(dist[nv] != std::numeric_limits<T>::max()) {
                    continue;
                }
                dist[nv] = dist[v] + 1;
                prev_edges[nv] = e;
                q.push(nv);
            }
        }
        return make_pair(dist, prev_edges);
    }

    std::pair<std::vector<T>, std::vector<Edge>> BFS01(const int& start) {
        std::vector<T> dist(N, std::numeric_limits<T>::max());
        std::deque<int> q;
        /**
         * @param prev_edges[target] : start から target までの最短経路における、targetを訪れる直前に通った辺
         */
        std::vector<Edge> prev_edges(N);
        dist[start] = 0;
        q.push_front(start);
        while (!q.empty()) {
            int v = q.front(); q.pop_front();
            for (const auto& e : G[v]) {
                int nv = e.to;
                if (dist[nv] <= dist[v] + e.cost) {
                    continue;
                }
                dist[nv] = dist[v] + e.cost;
                prev_edges[nv] = e;
                if (e.cost == 0) {
                    q.push_front(nv);
                } else {
                    q.push_back(nv);
                }
            }
        }
        return make_pair(dist, prev_edges);
    }

    std::pair<std::vector<T>, std::vector<Edge>> Dijkstra(int start) {
        std::vector<T> dist(N, std::numeric_limits<T>::max());
        std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int>>, std::greater<std::pair<T, int>>> q;
        /**
         * @param prev_edges[target] : start から target までの最短経路における、targetを訪れる直前に通った辺
         */
        std::vector<Edge> prev_edges(N);
        dist[start] = 0;
        q.push({dist[start], start});
        while (!q.empty()) {
            auto [dist_v, v] = q.top(); q.pop();
            if (dist_v > dist[v]) {
                continue;
            }
            for (const auto& e : G[v]) {
                int nv = e.to;
                if(dist[nv] <= dist[v] + e.cost) {
                    continue;
                }
                dist[nv] = dist[v] + e.cost;
                prev_edges[nv] = e;
                q.push({dist[nv], nv});
            }
        }
        return make_pair(dist, prev_edges);
    }

    /**
     * @brief 負辺を含むグラフで、単一始点の最短経路を求める
     * @return 負閉路を含む場合かどうかのフラグ、dist 配列
     * @remark 全辺のコストを -1 倍すると、最長経路を求める
     */
    std::pair<std::vector<T>, bool> bellman_ford(int start) {
        const T INF_ = std::numeric_limits<T>::max();
        std::vector<T> dist(N, INF_);
        dist[start] = 0;
        int cnt = 0;
        std::vector<Graph::Edge> es = edges();
        /**
         * 全ての辺を走査して緩和を行う
         * https://qiita.com/muumu/items/bae1575c3161ced28587
         * 各 while ループで、
         * 長さ 1 の最短路が決定 -> 長さ 2 の最短路が決定 -> ...
         * みたいな感じ?
         */
        while (cnt < N) {
            bool end = true;
            for (const auto& e : es) {
                if (dist[e.from] != INF_ and dist[e.from] + e.cost < dist[e.to]) {
                    dist[e.to] = dist[e.from] + e.cost;
                    end = false;
                }
            }
            if (end) {
                break;
            }
            cnt++;
        }
        return make_pair(dist, (cnt == N));
    }

    std::vector<Edge> path(const int& start, const int& target, const std::vector<Edge>& prev_edges) {
        std::vector<Edge> path;
        for (int cur = target; cur != start; cur = prev_edges[cur].from) {
            if (prev_edges[cur].id == -1) {
                return {};
            }
            path.push_back(prev_edges[cur]);
        }
        std::reverse(path.begin(), path.end());
        return path;
    }
};

template <typename T = int>
struct Tree : Graph<T> {
private:
    using Graph<T>::Dijkstra;
    using Graph<T>::BFS;
    using Edge = typename Graph<T>::Edge;
    int root;
    int N;
    std::vector<int> parent, depth, siz;
    std::vector<T> weighted_depth;
    bool done_build;

public:
    Tree(int N, int root = 0) : Graph<T>(N), root(root), N(N), parent(N, -1), depth(N, -1), siz(N, 0), weighted_depth(N, T(0)), done_build(false) {}
    void read(bool weighted = false, bool directed = false, int padding = 1) {
        Graph<T>::read(N - 1, weighted, directed, padding);
        if (!done_build) {
            build();
            done_build = true;
        }
    }
    int get_root() const { return root; }
    int get_parent(int v) const { return parent[v]; }
    int get_depth(int v) const { return depth[v]; }
    int get_size(int v) const { return siz[v]; }
    T get_weighted_depth(int v) const { return weighted_depth[v]; }
    int size() const { return N; }

    void build() {
        if (done_build) {
            return;
        }
        done_build = true;
        auto dfs = [&](auto dfs, int v, int p, int d, T wd) -> void {
            parent[v] = p;
            depth[v] = d;
            weighted_depth[v] = wd;
            int cnt = 0;
            for (const auto& e : (*this)[v]) {
                if (e.to == p) {
                    continue;
                }
                dfs(dfs, e.to, v, d + 1, wd + e.cost);
                cnt += siz[e.to];
            }
            cnt++;
            siz[v] = cnt;
        };
        dfs(dfs, root, -1, 0, T(0));
    }

    // 木の直径 ===========================================
    std::vector<int> get_tree_diameter(int x = 0) {
        std::vector<T> dist;
        std::vector<Edge> prev_edges(N);
        if (this->is_weighted) {
            std::tie(dist, prev_edges) = Dijkstra(x);
        } else {
            std::tie(dist, prev_edges) = BFS(x);
        }
        auto get_farthest_vertex = [this](std::vector<T>& dist) {
            T max_dist = std::numeric_limits<T>::lowest();
            int to = -1;
            for (int v = 0; v < this->N; v++) {
                if (max_dist < dist[v]) {
                    max_dist = dist[v];
                    to = v;
                }
            }
            return to;
        };
        int y = get_farthest_vertex(dist);
        if (this->is_weighted) {
            std::tie(dist, prev_edges) = Dijkstra(y);
        } else {
            std::tie(dist, prev_edges) = BFS(y);
        }
        int z = get_farthest_vertex(dist);
        std::vector<int> path;
        int v = z;
        while (1) {
            path.push_back(v);
            if (v == y) {
                break;
            }
            v = prev_edges[v].from;
        }
        std::reverse(path.begin(), path.end());
        return path;
    }
};

using ll = long long;
using lll = __int128_t;
using ld = long double;
#define newl '\n'
#define REF const auto&
#define INF 1000390039
#define LLINF 1000000039000000039
#define IMAX INT_MAX
#define IMIN INT_MIN
#define LLMAX LONG_LONG_MAX
#define LLMIN LONG_LONG_MIN
#define BIT(i) (1LL << (i))
#define tbit(n, k) ((n >> k) & 1) // nの(上から)kビット目
#define bit(n, k) (n & (1LL << (k))) // nの(下から)kビット目
#define PI acosl(-1)
#define inr(l, x, r) (l <= x && x < r)
#define einr(l, x, r) (l <= x && x <= r)
#define rep(i, a, b) for(int i = (a); i < (b); i++)
#define erep(i, a, b) for(int i = (a); i <= (b); i++)
#define rrep(i, a, b) for(int i = (a); i >= (b); i--)
#define repl(i, a, b) for(long long i = (a); i < (b); i++)
#define erepl(i, a, b) for(long long i = (a); i <= (b); i++)
#define rrepl(i, a, b) for(long long i = (a); i >= (b); i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define for_subset(sub, bit) for (ll sub = (bit); sub >= 0; sub = (sub == 0 ? -1 : (sub - 1) & (bit)))
#define UNIQUE(v) (std::sort(all(v)), (v).erase(std::unique(all(v)), (v).end()))
#define pcnt(x) __builtin_popcount(x)
#define llpcnt(x) __builtin_popcountll(x)
// 1D
#define VC(name, type, ...) \
    vector<type> name( \
        __VA_ARGS__ \
    )
// 2D
#define VVC(name, type, a, ...) \
    vector<vector<type>> name( \
        (a), vector<type>( \
            __VA_ARGS__ \
        ) \
    )
// 3D
#define VVVC(name, type, a, b, ...) \
    vector<vector<vector<type>>> name( \
        (a), vector<vector<type>>( \
            (b), vector<type>( \
                __VA_ARGS__ \
            ) \
        ) \
    )
// 4D
#define VVVVC(name, type, a, b, c, ...) \
    vector<vector<vector<vector<type>>>> name( \
        (a), vector<vector<vector<type>>>( \
            (b), vector<vector<type>>( \
                (c), vector<type>( \
                    __VA_ARGS__ \
                ) \
            ) \
        ) \
    )
// 5D
#define VVVVVC(name, type, a, b, c, d, ...) \
    vector<vector<vector<vector<vector<type>>>>> name( \
        (a), vector<vector<vector<vector<type>>>>( \
            (b), vector<vector<vector<type>>>( \
                (c), vector<vector<type>>( \
                    (d), vector<type>( \
                        __VA_ARGS__ \
                    ) \
                ) \
            ) \
        ) \
    )
// 6D
#define VVVVVVC(name, type, a, b, c, d, e, ...) \
    vector<vector<vector<vector<vector<vector<type>>>>>> name( \
        (a), vector<vector<vector<vector<vector<type>>>>>( \
            (b), vector<vector<vector<vector<type>>>>( \
                (c), vector<vector<vector<type>>>( \
                    (d), vector<vector<type>>( \
                        (e), vector<type>( \
                            __VA_ARGS__ \
                        ) \
                    ) \
                ) \
            ) \
        ) \
    )
template <typename T>
int lwb(const std::vector<T>& vec, const T& x){
    return lower_bound(all(vec), x) - vec.begin();
}
template <typename T>
int upb(const std::vector<T>& vec, const T& x){
    return upper_bound(all(vec), x) - vec.begin();
}
template <typename T>
T max(const std::vector<T>& vec){ return *max_element(all(vec)); }
template <typename T>
T min(const std::vector<T>& vec){ return *min_element(all(vec)); }
template <typename T>
T rad(const T& x){ return x * PI/180; }
template <typename T>
using maxpq = std::priority_queue<T>;
template <typename T>
using minpq = std::priority_queue<T, std::vector<T>, std::greater<T>>;
// 最大値・最小値の更新
template <typename T1, typename T2>
bool chmax(T1 &a, const T2& b){
    if (a < b) { a = b; return 1; }
    return 0;
}
template <typename T1, typename T2>
bool chmin(T1 &a, const T2& b){
    if (a > b) { a = b; return 1; }
    return 0;
}
/**
 * @brief (dx, dy) を基準として、(x, y) の偏角を求める。
 * @remark 弧度法で、[0, 2π) の範囲で返す
 * @remark cw=true なら時計回り
 */
ld calc_arg(ld x, ld y, ld dx = 1, ld dy = 0, bool cw = false) {
    assert(x != 0 or y != 0);
    assert(dx != 0 or dy != 0);
    
    ld c = dx * y - dy * x; // 外積
    ld d = dx * x + dy * y; // 内積
    ld theta = atan2l(cw ? -c : c, d);
    if (theta < 0) {
        theta += 2.0L * PI;
    }
    return theta;
}
__int128 cross(__int128 x1, __int128 y1, __int128 x2, __int128 y2) { return x1 * y2 - y1 * x2; };
bool is_clockwise(__int128 x1, __int128 y1, __int128 x2, __int128 y2) { return cross(x1, y1, x2, y2) < 0; }
bool is_counter_clockwise(__int128 x1, __int128 y1, __int128 x2, __int128 y2) { return cross(x1, y1, x2, y2) > 0; }
bool is_collinear(__int128 x1, __int128 y1, __int128 x2, __int128 y2) { return cross(x1, y1, x2, y2) == 0; }
/**
 * @brief 弧度法 -> 度数法
 */
ld rad_to_deg(ld rad) {
    return rad * 180.0L / PI;
}
/**
 * @brief 度数法 -> 弧度法
 */
ld deg_to_rad(ld deg) {
    return deg * PI / 180.0L;
}

const int di4[4] = {0, -1, 0, 1};
const int dj4[4] = {1, 0, -1, 0};
const int di8[8] = {0, -1, -1, -1, 0, 1, 1, 1};
const int dj8[8] = {1, 1, 0, -1, -1, -1, 0, 1};

bool out_of_grid(const int& i, const int& j, const int& h, const int& w){
    if(i < 0 || j < 0 || i >= h || j >= w) return true;
    return false;
}

namespace math {

    ll pow(ll N, ll e) {
        ll res = 1;
        while (e) {
            if (e & 1) {
                res *= N;
            }
            N *= N;
            e >>= 1;
        }
        return res;
    }

    template <typename T>
    T floor (const T& x, const T& m) {
        T r = (x % m + m) % m;
        return (x - r) / m;
    }

    template <typename T>
    T ceil (const T& x, const T& m) {
        return floor(x + m - 1, m);
    }

    /**
     * @brief floor(sqrt(N)) を求める
     */
    template <typename T>
    T sqrt_floor(T N) {
        assert(N >= 0);
        ll R = sqrt(N);
        // R*R>N なら大きすぎるので減らす
        while (R * R > N) {
            R--;
        }
        // 二乗して N を超えないギリギリまで増やす
        while ((R + 1) * (R + 1) <= N) {
            R++;
        }
        return R;
    }

    /**
     * @brief ceil(sqrt(N)) を求める
     */
    template <typename T>
    T sqrt_ceil(T N) {
        ll R = sqrt_floor(N);
        if (R * R == N) {
            return R;
        }
        return R + 1;
    }

    int log2_floor(ll N) {
        int res = -1;
        while (N != 0) {
            res++;
            N /= 2;
        }
        return res;
    }

} // namespace math

template <typename T, typename F>
T bisect(T& ok, T& ng, const F& f) {
    while (std::abs(ok - ng) > 1) {
        T mid = (ok - ng) / 2 + ng;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template <typename T, typename F>
T bisect_real(T& ok, T& ng, const F& f, int itr = 80) {
    while (itr--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

#include <fstream>

std::ofstream debug_outfile;
std::ostream* debug_out = &std::cout;

void Initialize_DebugOutput(){
    debug_outfile.open("debug.txt");
    debug_out = &debug_outfile;
}

#ifdef LOCAL

namespace debug {

    template <typename T>
    void debug_print(const T& t){
        *debug_out << t;
    }

    template <typename T, typename... Args>
    void debug_print(const T& t, const Args&... args){
        *debug_out << t << ", ";
        debug_print(args...);
    }

    // pair
    template <typename T1, typename T2>
    void debug_print(const std::pair<T1, T2>& p){
        *debug_out << "{" << p.first << ", " << p.second << "}";
    }

    // tuple
    template <typename Tuple, std::size_t... Is>
    void print_tuple(const Tuple& t, std::index_sequence<Is...>){
        ((*debug_out << (Is == 0 ? "" : ", ") << std::get<Is>(t)), ...);
    }

    template <typename... Args>
    void debug_print(const std::tuple<Args...>& t){
        *debug_out << "{";
        print_tuple(t, std::index_sequence_for<Args...>{});
        *debug_out << "}";
    }

    // map
    template <typename Key, typename Value>
    void debug_print(const std::map<Key, Value>& m){
        *debug_out << "{\n";
        for(auto it = m.begin(); it != m.end(); it++){
            if(it != m.begin()) *debug_out << ",\n";
            debug_print(*it);
        }
        *debug_out << "\n}";
    }

    // set
    template <typename T>
    void debug_print(const std::set<T>& s){
        *debug_out << "{";
        for(auto it = s.begin(); it != s.end(); it++){
            if(it != s.begin()) *debug_out << ", ";
            *debug_out << *it;
        }
        *debug_out << "}";
    }

    // 1D vector
    template <typename T>
    void debug_print(const std::vector<T>& vec){
        *debug_out << "[";
        bool f = std::is_integral<T>::value || std::is_floating_point<T>::value || std::is_same<T, char>::value;
        for(size_t i = 0; i < vec.size(); i++){
            if(!f){
                *debug_out << '\n';
            }
            debug_print(vec[i]);
            if(i != vec.size() - 1) *debug_out << ", ";
        }
        if(!f){
            *debug_out << '\n';
        }
        *debug_out << "]";
    }

    // 2D vector
    template <typename T>
    void debug_print(const std::vector<std::vector<T>>& vec){
        *debug_out << "[\n";
        for(const auto& row : vec){
            *debug_out << "  ";
            debug_print(row);
            *debug_out << "\n";
        }
        *debug_out << "]";
    }

} // namespace debug

#define debug(...) do{ \
    *debug_out << #__VA_ARGS__ << " = "; \
    debug::debug_print(__VA_ARGS__); \
    *debug_out << '\n'; \
} while(0)
#else
#define debug(...) do {} while(0)
#endif

namespace input {

    template <typename T>
    void read(T& t) {
        std::cin >> t;
    }

    template <typename T, typename... Args>
    void read(T& t, Args&... args) {
        std::cin >> t;
        read(args...);
    }

} // namespace input

#define READ(type, ...) \
    type __VA_ARGS__; \
    input::read(__VA_ARGS__)
#define INT(...) READ(int, __VA_ARGS__)
#define LL(...) READ(long long, __VA_ARGS__)
#define DOUBLE(...) READ(double, __VA_ARGS__)
#define LD(...) READ(long double, __VA_ARGS__)
#define STRING(...) READ(std::string, __VA_ARGS__)
#define CHAR(...) READ(char, __VA_ARGS__)
#define VI(vec, type, a) std::vector<type> vec(a); for(int i = 0; i < a; i++) std::cin >> vec[i]
#define VI2(vec1, vec2, type, a, b) std::vector<type> vec1(a), vec2(b); for (int i = 0; i < a; i++) std::cin >> vec1[i]; for (int i = 0; i < b; i++) std::cin >> vec2[i]
#define VI3(vec1, vec2, vec3, type, a, b, c) std::vector<type> vec1(a), vec2(b), vec3(c); for (int i = 0; i < a; i++) std::cin >> vec1[i]; for (int i = 0; i < b; i++) std::cin >> vec2[i]; for (int i = 0; i < c; i++) std::cin >> vec3[i]
#define VI4(vec1, vec2, vec3, vec4, type, a, b, c, d) std::vector<type> vec1(a), vec2(b), vec3(c), vec4(d); for (int i = 0; i < a; i++) std::cin >> vec1[i]; for (int i = 0; i < b; i++) std::cin >> vec2[i]; for (int i = 0; i < c; i++) std::cin >> vec3[i]; for (int i = 0; i < d; i++) std::cin >> vec4[i]
#define VI5(vec1, vec2, vec3, vec4, vec5, type, a, b, c, d, e) std::vector<type> vec1(a), vec2(b), vec3(c), vec4(d), vec5(e); for (int i = 0; i < a; i++) std::cin >> vec1[i]; for (int i = 0; i < b; i++) std::cin >> vec2[i]; for (int i = 0; i < c; i++) std::cin >> vec3[i]; for (int i = 0; i < d; i++) std::cin >> vec4[i]; for (int i = 0; i < e; i++) std::cin >> vec5[i]
#define VI2_(vec1, vec2, type, a) std::vector<type> vec1(a), vec2(a); for (int i = 0; i < a; i++) std::cin >> vec1[i] >> vec2[i]
#define VI3_(vec1, vec2, vec3, type, a) std::vector<type> vec1(a), vec2(a), vec3(a); for (int i = 0; i < a; i++) std::cin >> vec1[i] >> vec2[i] >> vec3[i]
#define VI4_(vec1, vec2, vec3, vec4, type, a) std::vector<type> vec1(a), vec2(a), vec3(a), vec4(a); for (int i = 0; i < a; i++) std::cin >> vec1[i] >> vec2[i] >> vec3[i] >> vec4[i]
#define VI5_(vec1, vec2, vec3, vec4, vec5, type, a) std::vector<type> vec1(a), vec2(a), vec3(a), vec4(a), vec5(a); for (int i = 0; i < a; i++) std::cin >> vec1[i] >> vec2[i] >> vec3[i] >> vec4[i] >> vec5[i]
#define VVI(vec, type, a, b) std::vector<std::vector<type>> vec(a, std::vector<type>(b)); for (int i = 0; i < a; i++) for (int j = 0; j < b; j++) std::cin >> vec[i][j]
#define VVVI(vec, type, a, b, c) std::vector<std::vector<std::vector<type>>> vec(a, std::vector<std::vector<type>>(b, std::vector<type>(c))); for (int i = 0; i < a; i++) for (int j = 0; j < b; j++) for (int k = 0; k < c; k++) std::cin >> vec[i][j][k]

template <int siz, int base, bool store_matches = false> // 文字列の種類数
struct AhoCorasick {
    struct Node {
        /**
         * @param accept なんらかの文字列の終端となっているか
         * @param cnt このノードで終わる(追加された)文字列集合の要素数
         * @param idxes このノードで終わる(追加された)文字列集合の要素の添え字
         */
        std::array<int, siz> nxt;
        std::array<bool, siz> is_child;
        int par;
        bool accept;
        int failure_link;
        int cnt;
        std::vector<int> idxes;
        Node() : par(-1), accept(false), failure_link(0), cnt(0), idxes() {
            for (int i = 0; i < siz; i++) {
                nxt[i] = -1;
                is_child[i] = false;
            }
        }
    };
    std::vector<Node> nodes;
    std::vector<int> ID;
    /**
     * @param M 文字列集合数
     */
    AhoCorasick(int M) : ID(M, -1) {
        nodes.emplace_back(Node());
    }
    /**
     * @brief idx 番目の文字列 S を追加する
     */
    void add(const std::string& S, int idx) {
        int pos = 0;
        for (char ch : S) {
            if (nodes[pos].nxt[ch - base] == -1) {
                nodes[pos].nxt[ch - base] = (int)nodes.size();
                nodes[pos].is_child[ch - base] = true;
                nodes.emplace_back(Node());
                nodes.back().par = pos;
            }
            pos = nodes[pos].nxt[ch - base];
        }
        nodes[pos].accept = true;
        nodes[pos].cnt++;
        if (store_matches) {
            nodes[pos].idxes.push_back(idx);
        }
        ID[idx] = pos;
    };
    /**
     * @brief idx 番目の文字列に対応する頂点番号を返す
     */
    int getID(int idx) {
        return ID[idx];
    }
    void build() {
        std::queue<int> q;
        for (int i = 0; i < siz; i++) {
            int c = nodes[0].nxt[i];
            if (c != -1) { // 根の子は全て failure_link=0
                q.emplace(c);
            } else {
                nodes[0].nxt[i] = 0;
            }
        }
        // 各状態の failure_link を、BFS 順で埋めていく
        while (!q.empty()) {
            /**
             * 親の failure_link を見る(ノードを X、それに対応する文字列を S とする)
             * -> もしそこから文字 i が生えているなら、文字列 S+i に対応するノードが c の failure_link になる
             * -> そうでないなら、X の failure_link を見る
             */
            int v = q.front(); q.pop();
            int f = nodes[v].failure_link;
            nodes[v].cnt += nodes[f].cnt;
            if (store_matches) {
                for (int i : nodes[f].idxes) {
                    nodes[v].idxes.push_back(i);
                }
            }
            for (int i = 0; i < siz; i++) {
                int c = nodes[v].nxt[i];
                bool child = nodes[v].is_child[i];
                if (c != -1 && child) { // 遷移先がある(ただし、子が存在するという意味で)
                    // 親 v の failure_link から i に対応する文字進んだ状態が、子 c の failure_link
                    nodes[c].failure_link = nodes[f].nxt[i];
                    q.emplace(c);
                } else { // 遷移先がない(子が存在しない)
                    // 親 v から、i に対応する文字の遷移で遷移先がないなら、
                    // 次行くべきなのは、親 v の failure_link から i に対応する文字進んだ状態
                    nodes[v].nxt[i] = nodes[f].nxt[i];
                }
            }
        }
    }
};

void FAST();

//const ll mod = ; using mint = atcoder::modint; atcoder::modint::set_mod(mod);
//const ll mod = 998244353; using mint = atcoder::modint998244353;
//const ll mod = 1000000007; using mint = atcoder::modint1000000007;

using namespace std;

/**
 * ```````````````````` ``````````````````````````.(ltOOOtz1?11<??JHfWpWXk\` ...(J+aAAWHHHa+JgkXvrrrrrrO=zOOw=~`` .JWUXXWUuuuXXXWpppppppppppppppppppppWSu
 * ``````````````````` `````````````````````````` (zttwvw1?????1(uXUHpbkdHXWWyWUUWWkkkXXVVVVVVVVWHHkmwvrvwv^  .(dWXXXfWSuuXXWppppppppppppppppppbbbppWHuuV
 * `````````````````` ```````````````````````````._OtrrXvOzzzuwZZwXXkMHWWWkkkkXyVVVyVVVWHWVVVVVVVWWyyyWHm....(XuXXXppfXuXWpppppppppppWWUYY""<!_`. .JSXXHY
 * `````````` `` ``` `` ` `` ``````` ````` ```````?-?OrOz4dWkZyyXWHWUUUUUWWWpWpHWkVVVVVVVVWHWVVVVVVWyyXkwXwuXWHHQWfpfWXppppppppbWUHMmgggggaAAwVTH8XXY!`.`
 * ````` `` ```` `   ``` ` `` `  `` `` ` ``` ``````` !?CzzdWHWkVKykXzzwXqkkHHHHHHHHHHHHHHWkfWHVyVVVVVVyVyWWWWkzzuUHHWppfpppWKY^_`````````` _.(wkV=~``. (d
 * `````` `` `` ``  ` ```` `` ``` ``` ``````` ` `````` ..?<1wWWWWyXkUWHVVVVVVVVVyyyyyyVfVffWWfVVVyVVVVfVVyyyyyyXXXZXUHkppWHh+J--.....(+dkWHW01-......+M@@
 * `` ``````` ```  `` `  `` `` ``` ` `` `  ````` .._<!```.vdWWWKWSwuXVfffVfVVffWWWQkHHHkkkfVkvWVVfWWWWfffVVyyyyyyyyAOXuHN@@@#MMHbWkHHHHbppppppppbHHHMMHHg
 * ```` `` ` ```  `  ` ``  `  `   ` ` ` `` `.._!```````.?(XWWWwUuuuXffpppWkHHHHWWpfpppHHHMNWfWdVVffVVfWHHkkfVVyyyyXkXXyXZWHbWWHHMHppppppppppppppppppppbbp
 * ```` ``` `` `  `` `  ` ` ` `` ` ` ` `` .!  ``````` (iJHHdfpkZZZZWpWkHHpppfpfppVVyVpppffpWfffffffffffffppHHWffVyVWHkXXVWkMM@#kWpppppppppppppfpppppppppp
 * ``` `` ````` ```````` ` ` `  `  ` ` ._``   `  ` ..7jzwWpppppWZZXHMHpppppfpfpfWVyWkHHppppfppfpHH@HkpppfpffVWHkffVyyyzUHkVWXMM@@@#HWWHHHMNkppppppppppppp
 * ````` `` `` `  `   `  ` `` ``` ` ` _``  ` ``.._!.(OwXUXyWpppWkHWXWWWpppppfppfWkHWVVyyVffppfpfppWHMNkffVVVVffWHpfffyzzWVHkyHWM@@#MSQMkbMMNkWppppppppppp
 * `` `` ```  ` ` ` `   `        ` ` ~` `` .._```.(1uUOrrzXXWWHWZ0T1dZypppffpfWHHpfVyWyVyVyfpVWfpfffpHMNpVVWpfpppHkfWuuuXyyyWWWWMMByWMMMHWZZZXHHppppppppp
 * `` `` ``  `` ` ` `  `  ` `        ..._~   ...((uZllttrrwQWUUZ=(dZZZZWpppfpWHpWWpfXXVVfffVfpVVyVVffpfHNpffffpffpWHWZZXXVyVyyWWWHXdBWZZZZZZZZZXppppppWWW
 * ``` `` `    ` `   ` `  `  `` .._<_-_::<~.~-<_(v?1=lltzAVXrw>(zwXZZZZXWWWkHpWWHfpXwfpffpfffffVffffpfppWNpppfpfpppWNWXXpfffyyyWNKHyOOZuuuZZZZZWWppWWWkHH
 * `` ````  ` ` `  `  `  ` ` .<!_<<::<<~<<<~<~_J>;>>?1lzd0ttv~(=lzOwXZZZQWHWWWHHffWOfpffpfppfffpfppffffppWNpfffpffppWMWWWpppffVHHyyykOltZUUUWHWH@@#HHpppp
 * ``` `    `` `  ` `   `  .>~_((<!`      -__(v(;;>>??u6<+lv-z1zzzzlOwX9CjSZXHUXpfSdffpfffffpffpfffpfpffffWHfppfpfpfWZHkppppppHWVyyyyZlllzzuuuuWMHppppppp
 * ` ```` `  ` ` ` `  `   J-J<!        `.!-_(!(:;;>>?dC?=z2(llttw0rzZ!~~(XuuWSuXWWzffffffffffpffffffffpfffpHfppfpWUZZZZMMHkppWHkffVyyZll=wvzzzuUMHppppppW
 * `` `` ` `  ` `  `  ` `.1^       `   _ ._J!(::;>>?v1??zZ(==llO0tZ^....(OOXHuuuu0dWpWfpfppfffpfpfppfWfffpfWHfpHSuZuuZXXHHHHHHNHpppfWwl=lOOOzzzwdkHWppWMH
 * ```` ` ``` ` ` ` `   `.! ` ` ``   .! ~(z!(::;;>>v1??dz1=??=zyzv~.....JtdzOwXuuIwXRuUWWWUUWffWWffffkfffffWHuuuWkZuZXfppHHHHHWHWpWHfZOztXyyyVfWkMHWHHpWp
 * ``` ``` ` `` `  `  `  . `   `    .` (?(~(::;;>>zz??dz0=???z=Zv_......wO%zz1lOXzwXkuuuuuuuuuuXkuuuXXXffpWuXkuuZWkuXffffpHfpppWMHpWQmQQQHHgHHQkyWMMkkWHH
 * `` `` ` ._`   `  `  `     `     (  /`.!.~<(;>>1C??dzwI??1v<_z!.`.....zd<Zlz?=z<OXKuuuuuuuuuuuWuuuuuZXWWXuXKuuuuUkXppffppHffpffHMM@@@#HHgHHHHWHWMmmHHHH
 * `  `` (???+?i--`` ` `` ` `  `  . .!  ~ __(;;>?z==j0wZ<<+C~_.-_`````.`(z.Ollz??<1dKXSuuuuuuuuuXuuuuXXwuuuuXHuuuXXWHWfpfpWWWWfpWHfHMMMH@@@#HHHMHMMMgHHQk
 *   ```(?zv?1+>>><+.  ` `  `  ` .~.!` /` (_:;>>1I=1kwOZ;<<i-..`.`.``.`.-j_(lwl=1+(IXzwXuuuuuuuuXXuuuXuwuuzzXHfVffWWUHSVwwAAQHfWHffWMM@@#MMHMMMMggggHHHyZ
 *  `` .wZ!``` ?1>;<(<<-. `  `  `_.~ `.~`.<(;>>?zI=dzwf(+x___<--.`.``.```.~_wdylll<I(kzZzwXuuXXuXRXuuXkwuwrrwTTOOwwAXWHHfffffHWHHffWMMM@@#HHHM@@#HHyyyZZZ
 * ````.Uk` ``` `_1+;;_~<_~~_....!-..<>` <~>>???==1kXf_.z}__..-1i.`.``.````.(ZXzl=z1.(ywz1zXWfffpHffWXHZzwwrtjdWfVfffffWqkffffMHfffWMMgMMMMMHHpfffffVyyyy
 * `````.O;`` ` ``  ?1<;;:_:__` .<~~~_:`.<(>??==z=duX~...~......_1-..`.`.`...(OzOll1-.(wwltOwXWfWNffffHkVVXXXXXVffffffffpHHWpWZwHfpHMNkkWffffpffffppfpfVy
 * ``` ``.X `  .......(?<<___:~~_1_ ` _ +<(??===zOdX\_...(.((m--.-1l....`..`.._?+1zlI_._1wllltOwWMpfffHkVyyZZXXZVfWXUUUUSOdHsAdWHpW@#MHHHHHHHHHWWWWffppWW
 * `` .-ztz+++(---   ``````  ```` ~ ` ~.z<(?===ldkdK~.jJd@MMMMMkW+_(l.....`..`..._-?7l_..(4lllltdMWWffqSfyZuwZ<usv0wdHpkfWffHHkfWk@@#fffffpffVyyVVVVWWH@@
 * `.X0wZzwzzvrwzv111+--.. ````````  ._.Jz<=llllwydK~(H@#Y<+gHHMMNh<(-...................._1z=llwVRwXWkXfVyXXwwXffpffffffffffWHHWW@MNffffffffVyVWWHgg@#HH
 * (0ldZzzzZOz1111zzzz++-(<<<<<~<<~((+O-dk<ttttttWyH(HH3~~(MH..JHMN/<.......`.`.............?z==dl4ttwWdVfffVWVfffffffVfffffWffMHHWMyyVVVfppkkHHHHHWpfpfp
 * wllwwuZ1?>>>+&??~`   ``_~~!!!?jSzzzwySXyzrvrrrdfH_Wf_~(HgHWHWHuWb............`............(O=d~(ZlOSzXWWfWHffffffffffffffWHVWNWWHHyyyyyffffffpfffpfppp
 * jOlwwuI??+zw=``` ` ..` ` `` _.uXuZZZZXkW2wzuzzzHH.?Wr~(HZzHWWWHHD~~.~~..................~.~(OS._I=dSlOOXUWMfffffpWffpWWfffWyyWMHWWHkyyyVfffpfppfpfpfpW
 *  jZwZuXzvzw\`  ` (z?=Oi.` `. ,zvwVXV777=?1XuuuuX@.::C~?StrWW8OHD3~.~~.~~.~.....(+7777777COOOW+--Zj3I===lOb#WWfffWHffffWWffWHyyWHHkWHWWWVffpffffpppb0o(
 * ``(zywUUXwd/` ` .1?====zO,`.. 4luW<` `````?4kuuzX&;::::O1<+1tOK<~~..~.~~~.~~.~.._<<!~((--..~..~(wC1C===ydW0ZwUWfWHfffffWWfVWyyyWKWHkWMWWHkWppfpfffppfp
 * ````.7XXI?+11+.`(Ov1zz===lOi__.4dyWe.````.JkZWWQXXk+;:::<<~+xC~~~.~~.~.~.~.~~~~~_(&HMMMNHWXJ(,~<~~(I==dwWWz1lOwXWHfpffffWffWHyyyWkyWHWHKHHkHHWkQkHpfpp
 * `````` 70?I>>>+:.I1zOrvvwv1zzO&-ZWVWWW&JUUuuuwZf_?TTTC<:::~~~~~~~~~~~.~~~.~~.~~(YCjM#^_?WMNM@e_..~v=uXWHXDv+==lOdKWVffpffXffNfVXVNVVVHkWkWffpHWppppfpp
 * ` `` ``.1d1?>>>z 1ztrrvZ!`` ?1zOwXuuuuuuuuuuzzXS.(;;;::::::~~~~~~~~~~~.~~~.~~~~~~(M@HHKXWWUMM@HC~(GZu0OWWv+====jHROwUWVffWWfWNfffWNfffWNWHpffffffpfppW
 * ```?Ozwv^J????1r`(zrrrrC``````.7vOOOZXXuuuuuzOdr.;;;;;::::::~__``_~~~~~~~~~~~~~~_d9Owqbb#HXdSM@b~(?7~(dXS+=====dWS==OOXXyVZfWMWfffMfffffNWHppppWkkH#=`
 * ``    ..J===?zC~:~?zOrvI` .<<<<.`?1ZVwzzuuuZ1wX].<:;;;:::::~:_`` ~~~~~~~~~~~~~~~(6tOdHWHIdgM<J@HC~~~~(H5+=====d8ZW==?1zOZX0XWMNfffWH@HHHHNM@@@@@#"~` (
 * `` .?6wsuuzZ=<:::::(CwrZ+````. {...JUAOltt1xtOAk.(;:;::::::::_` ~~~~~~~~~~~~~~~~?6<<+zZztdH3(JWK<~.~_Z1=?===?uKz?dv??<>?=zOzXMHKVfWM@@@@@MM@HY"````.dp
 * ~~<::;;;:;:::::::::::~??77<_` ~11==z?7!?7>TUWY(J[.<::;:::::::::<::~:~~~~~~~~::::::<:<;+OzY~(dX=~~~~-JIz=????1WZuudI>>>>>???<dWHNZyW@g@@@@M"!`````.(Hff
 * .`-<;:;;:::::::::::~~``````` `  ..._<?0UOWp=(OXwX/-<;;:::::::~:::::::::::::::::::::::<7<__?C<::~~_JZ1z1?>>>+ITuuuXP>;>;;;;;<XzXWwXWmHY=~?````. .JWVyVV
 * _+<<1++<;;;;;;;::::_- ..._~<<!~....`.(OCXV<dSXfWVWo-;;:;:::::::::~:::::::~:::::::;:;:;:;::<+++++z0ww0=?>>>+>__zrwwD;;::;:::<ZwzV+dnJ-.. `` .(dWyVyyVWV
 * +<I>>>1+1I++;;;;;;<c?>_........`.`..._~(V+VXWpbpXpHn_;;;;::;1+::::::::::::::::;;;;;;;<u&<:;;?7TWWUwttl??+v<~<<ztzOS;;:::::jCzzwCJXwwZXUWUXUZyyyVyVyWS!
 * zOOzzz<<>zzv;+++zzIOI&-_<<---...`.....(+uVWWpbbkRWHzS(;;;;;;;:<;;::::::::::;;;;;;;;;;;;+TXXUU0vrrrrttwy6<.._<<1ttdI:;;;:;+I(+zz>:;;>>?1zOwwzuZyyyWY!``
 * <<?1ztvzj1<<<<+1+>jz<>>+(<>+(?<1_~____jdWpWbkkkHNkWZ=vx;;;;;;;;;;<+11&+:;;;;;;;;;;;;;;;;+1+OWUXwwOOv7<<<((uwrz<<1d<::::;JC><:::::::;;;>?1zzOwXuXXWkka-
 * 1<<+z17<<<<(><z>OxOzzOzI????<+GjwO+_(jkWkkkkqqHWHWXHz=zS+;;;;;;;;;;;;;;;;;;;;;;;;;;;;>;><+&Mc<<<::_(J+gWZZZuzvrOjS;;;;jZ+<(::::::::::;;>>?1ud6wdHpbkkq
 * ZO<::(<>++(1+;zzdWHHmzzIl=l===znXWWyzWfHqqqmmHWXWlXXS<::?x>;;>;;;>;>;;>>;;;;;;;;;;;>>;j&UGdWWNkXWWZuXWWkXWHkkZuAD>;+JUOXIJOz++<;:::<+++xOOwV?1dXZyfpbb
 * ;j<+z;;;>+v:11jHpppppWkO1ll====vkkbpXkbHmmmmHZZXWO04Xy:::?S<>>>>>>>>>>>>>>>;>;;;>+i&ZY<;JwjWMyyyuZZZHZuuuXWXXWHkswUwrO&+OwGx<111111????1xV<;j0lOwXXyVp
 * ;j<;<?11<::;+wHffpppfpkWz1l=====RHHbqbbHHUUXWyyyWf<<HW<:::;ze&&&&&&&&&&&&&&&zZVTC<>;>;;;j3(MkyyZwyyXWyyWWkXuXkuZuXWkXvrrttttZ0y&z???1+vC;:;jC?==lOwXXy
 * <+z1++;;;++ZwdVVfffW9UWkXnC1zz=u0XHpHUY=_jkuwXUUR;;;dW2;:::jRzSzS<>>>>>>>>>>>>>>>;>>;>+J>(HkkHWSdyyWVVyyyyWRZXWkyZZwwXXwzzzOttttOTTC<;;;;<J?????=1zzOX
 * z+z;++z1z1zwvXyyVVfD==llVXs-.` _``.``..(XXXXffkXD;jdHW>;;::+Sv`Ow_<>>?>???>>>>>>>>>>++3::JHqkkHkXZdbVVVVVVW91><dkyyZZXwzwwZOOz+++;;;;;<++==?????<<::;;
 * >+I?C++CzI=zOIUWyyWr<<1z<<zXo-. ```..JwXXwfffffWWggHB3;:;;:<z_` 7..(>>>?>?????>>?1&vuJZT=dqqkkkXySwpVVVVVVK>;;;;?HyyyyyyXXzvOzz=v<~<?<<+=======?+(::::
 * uxI+++I;>Zz1<!`(4XX[``  JVwwwkUmAwzu0XzwXfpppWHgHBY<;;;;;:;;(-``` ?11&&+1???1&z7OxC>::::(dqkkkKXHZzWWyVVVWS;;>;>;?HkfVyyVVfVXXXw<___.._<1=========??++
 * dyyWSCz1??<! ```` _?! _ UdWVVVyVyWHHHHHHgNBU6zzO<;::::::;+zljl.````` _:;;;<:<jv3<::::::<+WkkkHXHSuOd+UkyWK;;;>>>;>+WHfffffffpfWWkG-_~...._?1==l=======
 * yyVVS???<~```````````_``(ZWHVfffWWWHbHHHHUXOOz<:::~~~:::<jc;Z;?<<-..(:;;+++?<;;:;;:;:;+zzMkbkWHSuuuuS?zWW>;;;;++&&swpMkpffffWpppbWWs-_~~~~.~_1llllll==
 * ZWWV1<<`````````````.````jdWkffWHgHHmmmHC>>>>>;::(!```-<<<vd><::__:<<?7<<;;:;::;;:;<+zlldHkHWHXZZZuuXz1d>>+udXfffWWfWpWMkpppfpbkkkkHWA+(_~~~~~_1llllll
 * uX6<!``` ..((<>>><(-_```` SWWfWHmm@Mmm#<>>>>>>;;::<-.. .<_(J(<<;:;:;;:;;;;;;;;;;;+zz1<<+dqHW8XXZZZZXZRdOdXfffffffffpfpfpWMkpppbkkkqqqqqWkkwz&+xzttrtzt
 * ZzlO+.(<>?????>????z<.````(ZVHHmHHHmH@>>>>>>>>>>;;;:;<?+<<<;;+;;<<;;;;;;><<>>>>>;>><<<1dHWHXzvvvvvwWZHX9TTOOOTUfffffffpfppWMHbbbkqqqqqqqqHkkXuzzvvrrrt
 * 11OOrwXx???>>>>>>>+>;!````.JdHHH@MHH@<>>>>>>>+z+>>>>;><++======>;<(uw00XXXXXA&++;;;;<jHHHHyyyXzzwXXdyHjI?++&zdXpWWpWVffffffppMNWkkkqkqqqmmmKUUUuuzzvvr
 * -<=wwrrwG+>>+<<<<<<<~ .-(<j6vWHHmqq@_(>>>>>+zOOtO+>>>>1ll====z<+JXvzzzwVC117WVVVWWHHMHWVyVyVVVWXSdHHWHWHHWHHHHHHHHHkWWWppffffppHMkkkqqqqqqmRlllz><?wuz
 * -_<?zOrrr0+v<_.``..__~(+77dzlvWXHqH!.(>>>>1IOjztttO+>>>>>>>;;;;drrvvw6>>>>>;jWVVVVXkkXXWWWWWWHpHHQHMkkHMHkpbbpbNWHffWHkWHWWfpffppbMNHqqqqqqRllllzz+dXZ
 * 一回目つまずき後悔してハイ。それで終わりでいいワケ? もう一度立ち上がるそんな君じゃなきゃ私は寂しい
 */

void solve() {

    STRING(S);
    int N = (int)S.size();
    INT(M);
    AhoCorasick<26, 'A'> aho(M);
    rep (i, 0, M) {
        STRING(T);
        aho.add(T, i);
    }
    aho.build();

    int ans = 0, pos = 0;
    rep (i, 0, N) {
        pos = aho.nodes[pos].nxt[S[i] - 'A'];
        ans += aho.nodes[pos].cnt;
    }

    cout << ans << newl;

}

int main() {
    FAST();

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }

}

void FAST() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
}
0