This documentation is automatically generated by online-judge-tools/verification-helper
#include "Library/String/Trie.hpp"文字列の集合を効率的に管理するデータ構造です。複数の文字列の共通接頭辞を共有することで省スペース化を図ります。
Trie(vector<string> &S_)
制約
計算量
Graph<int32_t> Build() const
計算量
vector<int> &operator[](const int i)
制約
計算量
#include "../Common.hpp"
#include "../Tree/Tree.hpp"
template<int MAXSIZE = 500010>
class Trie{
public:
Trie(vector<string> &S_) : S(S_), n((int)S_.size()), v(1), vertex_(n), child_(MAXSIZE){
for(int i = 0; i < MAXSIZE; ++i){
child_[i].fill(-1);
}
for(int i = 0; i < n; ++i){
int p = 0, m = S[i].size();
vertex_[i].resize(m + 1, 0);
for(int j = 0; j < m; ++j){
int c = S[i][j] - 'a';
if(child_[p][c] == -1){
child_[p][c] = v++;
}
p = child_[p][c];
vertex_[i][j + 1] = p;
}
}
}
Graph<int32_t> Build() const {
Graph<int32_t> ret(v);
for(int i = 0; i < v; ++i){
for(int j = 0; j < 26; ++j){
if(child_[i][j] == -1) continue;
ret.AddUndirectedEdge(i, child_[i][j]);
}
}
return ret;
}
vector<int> &operator[](const int i){
return vertex_[i];
}
private:
vector<string> &S;
int n, v;
vector<vector<int>> vertex_;
vector<array<int, 26>> child_;
};#line 2 "Library/Common.hpp"
/**
* @file Common.hpp
*/
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cstdint>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;
using ll = int64_t;
using ull = uint64_t;
constexpr const ll INF = (1LL << 62) - (3LL << 30) - 1;
#line 2 "Library/Tree/Tree.hpp"
#line 2 "Library/Graph/Graph.hpp"
#line 4 "Library/Graph/Graph.hpp"
using Vertex = int;
template<typename WeightType = int32_t>
struct Edge{
public:
Edge() = default;
Edge(Vertex from_, Vertex to_, WeightType weight_ = 1, int idx_ = -1) :
from(from_), to(to_), cost(weight_), idx(idx_){}
bool operator<(const Edge<WeightType> &e) const {return cost < e.cost;}
operator int() const {return to;}
Vertex from, to;
WeightType cost;
int idx;
};
template<typename WeightType = int32_t>
class Graph{
public:
Graph() = default;
Graph(int V) : edge_size_(0), adjacent_list_(V){}
inline void AddUndirectedEdge(Vertex u, Vertex v, WeightType w = 1){
int idx = edge_size_++;
adjacent_list_[u].push_back(Edge<WeightType>(u, v, w, idx));
adjacent_list_[v].push_back(Edge<WeightType>(v, u, w, idx));
}
inline void AddDirectedEdge(Vertex u, Vertex v, WeightType w = 1){
int idx = edge_size_++;
adjacent_list_[u].push_back(Edge<WeightType>(u, v, w, idx));
}
inline size_t VertexSize() const {
return adjacent_list_.size();
}
inline size_t EdgeSize() const {
return edge_size_;
}
inline vector<Edge<WeightType>> &operator[](const Vertex v){
return adjacent_list_[v];
}
inline const vector<Edge<WeightType>> &operator[](const Vertex v) const {
return adjacent_list_[v];
}
private:
size_t edge_size_;
vector<vector<Edge<WeightType>>> adjacent_list_;
};
template<typename WeightType = int32_t>
Graph<WeightType> InputGraph(int N, int M, int padding = -1, bool weighted = false, bool directed = false){
Graph<WeightType> G(N);
for(int i = 0; i < M; ++i){
Vertex u, v; WeightType w = 1;
cin >> u >> v, u += padding, v += padding;
if(weighted) cin >> w;
if(directed) G.AddDirectedEdge(u, v, w);
else G.AddUndirectedEdge(u, v, w);
}
return G;
}
#line 4 "Library/Tree/Tree.hpp"
template<typename WeightType = int32_t>
Graph<WeightType> InputTree(int V, int padding = -1, bool weighted = false){
Graph<WeightType> G(V);
for(int i = 0; i < V - 1; ++i){
Vertex u, v; WeightType w = 1;
cin >> u >> v, u += padding, v += padding;
if(weighted) cin >> w;
G.AddUndirectedEdge(u, v, w);
}
return G;
}
template<typename WeightType = int32_t>
Graph<WeightType> InputRootedTreeChild(int V, int padding = -1){
Graph<WeightType> G(V);
for(Vertex u = 0; u < V; ++u){
int k; cin >> k;
for(int i = 0; i < k; ++i){
Vertex v; cin >> v, v += padding;
G.AddUndirectedEdge(u, v);
}
}
return G;
}
template<typename WeightType = int32_t>
Graph<WeightType> InputRootedTreeParent(int V, int padding = -1){
Graph<WeightType> G(V);
for(Vertex u = 1; u < V; ++u){
Vertex v; cin >> v, v += padding;
G.AddUndirectedEdge(u, v);
}
return G;
}
template<typename WeightType = int32_t>
vector<vector<Vertex>> RootedTreeAdjacentList(const Graph<WeightType> &T, const Vertex r = 0){
int V = T.VertexSize();
vector<vector<Vertex>> ret(V);
auto rec = [&](auto &self, Vertex u, Vertex p) -> void {
for(Vertex v : T[u]){
if(v == p) continue;
ret[u].push_back(v);
self(self, v, u);
}
};
rec(rec, r, -1);
return ret;
}
template<typename WeightType>
vector<Vertex> CalculateTreeParent(Graph<WeightType> &T, Vertex r = 0){
int V = T.VertexSize();
vector<Vertex> ret(V, -1);
auto rec = [&](auto &self, Vertex u) -> void {
for(Vertex v : T[u]){
if(v == ret[u]) continue;
ret[v] = u;
self(self, v);
}
};
rec(rec, r);
return ret;
}
template<typename WeightType>
vector<WeightType> CalculateTreeCost(Graph<WeightType> &T, Vertex r = 0){
int V = T.VertexSize();
vector<WeightType> ret(V);
auto rec = [&](auto &self, Vertex u, Vertex p) -> void {
for(const Edge<WeightType> &e : T[u]){
Vertex v = e.to;
if(v == p) continue;
ret[v] = e.cost;
self(self, v, u);
}
};
rec(rec, r, -1);
return ret;
}
template<typename WeightType>
vector<int> CalculateTreeDepth(Graph<WeightType> &T, Vertex r = 0){
int V = T.VertexSize();
vector<int> ret(V, 0);
auto rec = [&](auto &self, Vertex u, Vertex p, int d) -> void {
ret[u] = d;
for(Vertex v : T[u]){
if(v == p) continue;
self(self, v, u, d + 1);
}
};
rec(rec, r, -1, 0);
return ret;
}
template<typename WeightType>
vector<WeightType> CalculateTreeDistance(Graph<WeightType> &T, Vertex r = 0){
int V = T.VertexSize();
vector<WeightType> ret(V, WeightType(INF));
auto rec = [&](auto &self, Vertex u) -> void {
for(const Edge<WeightType> &e : T[u]){
if(ret[e.to] > ret[u] + e.cost){
ret[e.to] = ret[u] + e.cost;
self(self, e.to);
}
}
};
ret[r] = 0;
rec(rec, r);
return ret;
}
template<typename WeightType>
vector<int> CalculateSubtreeSize(Graph<WeightType> &tree, Vertex r = 0){
int V = tree.VertexSize();
vector<int> ret(V, 1);
auto rec = [&](auto self, Vertex u, Vertex p) -> int {
for(const int v : tree[u]){
if(v == p) continue;
ret[u] += self(self, v, u);
}
return ret[u];
};
rec(rec, r, -1);
return ret;
}
#line 3 "Library/String/Trie.hpp"
template<int MAXSIZE = 500010>
class Trie{
public:
Trie(vector<string> &S_) : S(S_), n((int)S_.size()), v(1), vertex_(n), child_(MAXSIZE){
for(int i = 0; i < MAXSIZE; ++i){
child_[i].fill(-1);
}
for(int i = 0; i < n; ++i){
int p = 0, m = S[i].size();
vertex_[i].resize(m + 1, 0);
for(int j = 0; j < m; ++j){
int c = S[i][j] - 'a';
if(child_[p][c] == -1){
child_[p][c] = v++;
}
p = child_[p][c];
vertex_[i][j + 1] = p;
}
}
}
Graph<int32_t> Build() const {
Graph<int32_t> ret(v);
for(int i = 0; i < v; ++i){
for(int j = 0; j < 26; ++j){
if(child_[i][j] == -1) continue;
ret.AddUndirectedEdge(i, child_[i][j]);
}
}
return ret;
}
vector<int> &operator[](const int i){
return vertex_[i];
}
private:
vector<string> &S;
int n, v;
vector<vector<int>> vertex_;
vector<array<int, 26>> child_;
};