---
tags: codebook
---
{%hackmd theme-dark %}
# suffix trie
```cpp=
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
constexpr size_t cAlphaSize = 128;
struct suffix_trie {
struct node {
size_t start, end, index;
node *slink;
vector<node*> next;
}*root, *needslink, *active_node;
string data;
size_t remainder, active_index, active_length;
size_t length(node* x) {
return min(x->end, data.size()) - x->start;
}
node* newnode(size_t a, size_t b = string::npos, size_t c = 0) {
node* x = new node;
x->start = a, x->end = b;
x->index = c ? c : data.size() - remainder;
x->next.assign(cAlphaSize, x->slink = root);
return x;
}
size_t active_edge() {return data[active_index];}
void addslink(node* x) {
if (needslink != root)
needslink->slink = x;
needslink = x;
}
bool walk_down(node* x) {
if (active_length < length(x))
return false;
active_index += length(x);
active_length -= length(x);
active_node = x;
return true;
}
void init() {
active_node = needslink = root = newnode(string::npos, string::npos);
active_index = active_length = remainder = 0;
root->next.assign(cAlphaSize, root->slink = root);
}
void extend(char c) {
data.push_back(c);
needslink = root, remainder++;
while (remainder > 0) {
if (!active_length)
active_index = data.size() - 1;
if (active_node->next[active_edge()] == root)
active_node->next[active_edge()] = newnode(data.size() - 1), addslink(active_node);
else {
node* nxt = active_node->next[active_edge()];
if (walk_down(nxt)) continue;
if (data[nxt->start + active_length] == c) {
active_length++;
addslink(active_node);
break;
}
node* split = newnode(nxt->start, nxt->start + active_length, string::npos);
active_node->next[active_edge()] = split;
split->next[size_t(c)] = newnode(data.size() - 1);
nxt->start += active_length;
split->next[size_t(data[nxt->start])] = nxt;
addslink(split);
}
remainder--;
if (active_node == root && active_length)
active_length--, active_index = data.size() - remainder;
else
active_node = active_node->slink;
}
}
void dfs(node* cur, vector<size_t>& v) {
if (cur == root) return;
if (cur->index != string::npos)
v.push_back(cur->index);
for (size_t i = 0; i != cAlphaSize; i++)
dfs(cur->next[i], v);
}
vector<size_t> search(const string& str) {
vector<size_t> v;
node* cur = root->next[str.front()];
size_t i = 0, j = 0;
while (cur != root && i < str.size()) {
if (j >= length(cur))
cur = cur->next[str[i]], j = 0;
if (str[i] != data[cur->start + j])
return v;
i++, j++;
}
if (cur != root)
dfs(cur, v);
return v;
}
bool count(const string& str) {
node* cur = root->next[str.front()];
size_t i = 0, j = 0;
while (cur != root && i < str.size()) {
if (j >= length(cur))
cur = cur->next[str[i]], j = 0;
if (str[i] != data[cur->start + j])
return false;
i++, j++;
}
return cur != root;
}
suffix_trie(const string & str) {
init();
for (const auto& i : str)
extend(i);
extend('\0');
}
};
ostream& operator<<(ostream& os, const vector<auto>& v) {
for (const auto& i : v)
os << i << ' ';
return os;
}
int main() {
string a, b;
while (cin >> a >> b)
cout << vector<string> {"No", "Yes"} [suffix_trie(b).count(a)] << endl;
return 0;
}
```