#include <string>
#include <vector>
#include <memory>
#include <cstring>
#include <iostream>
template<size_t K>
struct vertex
{
int next[K]; // index to the next vertex by char
bool leaf; // is terminal
int p; // parent vertex
char pch; // parent char which leads to this vertex
int link; // suffix link
int go[K]; // automaton goto function
int out; // suffix link to leaf
int key_idx; // index of key
};
template<size_t K = 26, size_t NMAX = 500>
class automaton
{
public:
automaton()
{
t[0].p = t[0].link = -1;
memset(t[0].next, 255, sizeof t[0].next);
memset(t[0].go, 255, sizeof t[0].go);
sz = 1;
}
void add_string (const std::string& s) {
int v = 0;
for (size_t i = 0; i < s.length(); ++i)
{
char c = s[i]-'a';
if (t[v].next[c] == -1) {
memset (t[sz].next, 255, sizeof t[sz].next);
memset (t[sz].go, 255, sizeof t[sz].go);
t[sz].link = -1;
t[sz].p = v;
t[sz].pch = c;
t[sz].leaf = false;
t[sz].out = -1;
t[v].next[c] = sz++;
}
v = t[v].next[c];
}
t[v].leaf = true;
keys.push_back(s);
t[v].key_idx = keys.size() - 1;
}
int get_link(int v) {
if (t[v].link == -1)
if (v == 0 || t[v].p == 0)
t[v].link = 0;
else
t[v].link = go(get_link(t[v].p), t[v].pch);
return t[v].link;
}
int go(int v, char c) {
if(t[v].go[c] == -1)
if(t[v].next[c] != -1)
t[v].go[c] = t[v].next[c];
else
t[v].go[c] = v==0 ? 0 : go(get_link(v), c);
return t[v].go[c];
}
int out(int v)
{
if(t[v].out == -1)
{
int u = get_link(v);
if(t[u].leaf)
t[v].out = u;
else if(u == 0)
t[v].out = 0;
else
t[v].out = out(u);
}
return t[v].out;
}
void check(int v, int i)
{
for(int u = v; v != 0; v = out(v))
{
if(t[u].leaf)
{
int k = t[u].key_idx;
std::cout << (i - keys[k].length() + 1)
<< " "
<< keys[k]
<< std::endl;
}
}
}
void check2(int v, int i)
{
{
if(t[v].leaf)
{
int k = t[v].key_idx;
std::cout << (i - keys[k].length() + 1)
<< " "
<< keys[k]
<< std::endl;
}
}
}
void find_all_occurrences(const std::string& text)
{
int v = 0;
for(int i = 0; i < text.length(); ++i)
{
v = go(v, text[i] - 'a');
check(v, i + 1);
}
}
private:
vertex<K> t[NMAX+1];
int sz;
std::vector<std::string> keys;
};
//
//class Solution {
//public:
// std::vector<std::string> wordBreak(std::string s,
// std::vector<std::string>& wordDict) {
//
//
// }
//};
void _test_1()
{
std::vector<std::string> dict = {"apple", "pen", "applepen",
"pine", "pineapple"};
std::string s = "pineapplepenapple";
automaton<> m;
for(const auto& k : dict)
m.add_string(k);
m.find_all_occurrences(s);
}
void _test_2()
{
std::vector<std::string> dict = {"abc", "bcdc", "cccb",
"bcdd", "bbbc"};
std::string s = "abcdcbcddbbbcccbbbcccbb";
automaton<> m;
for(const auto& k : dict)
m.add_string(k);
m.find_all_occurrences(s);
}
int main()
{
std::cout<<"Test 1:"<<std::endl;
_test_1();
std::cout<<"Test 2:"<<std::endl;
_test_2();
return 0;
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHNpemVfdCBLPgpzdHJ1Y3QgdmVydGV4CnsKICAgICAgICBpbnQgbmV4dFtLXTsgICAgLy8gaW5kZXggdG8gdGhlIG5leHQgdmVydGV4IGJ5IGNoYXIKICAgICAgICBib29sIGxlYWY7ICAgICAgLy8gaXMgdGVybWluYWwKICAgICAgICBpbnQgcDsgICAgICAgICAgLy8gcGFyZW50IHZlcnRleAogICAgICAgIGNoYXIgcGNoOyAgICAgICAvLyBwYXJlbnQgY2hhciB3aGljaCBsZWFkcyB0byB0aGlzIHZlcnRleAogICAgICAgIGludCBsaW5rOyAgICAgICAvLyBzdWZmaXggbGluawogICAgICAgIGludCBnb1tLXTsgICAgICAvLyBhdXRvbWF0b24gZ290byBmdW5jdGlvbgogICAgICAgIGludCBvdXQ7ICAgICAgICAvLyBzdWZmaXggbGluayB0byBsZWFmCiAgICAgICAgaW50IGtleV9pZHg7ICAgIC8vIGluZGV4IG9mIGtleQp9OwoKCnRlbXBsYXRlPHNpemVfdCBLID0gMjYsIHNpemVfdCBOTUFYID0gNTAwPgpjbGFzcyBhdXRvbWF0b24KewpwdWJsaWM6CiAgICAgICAgYXV0b21hdG9uKCkKICAgICAgICB7CiAgICAgICAgICAgICAgICB0WzBdLnAgPSB0WzBdLmxpbmsgPSAtMTsKICAgICAgICAgICAgICAgIG1lbXNldCh0WzBdLm5leHQsIDI1NSwgc2l6ZW9mIHRbMF0ubmV4dCk7CiAgICAgICAgICAgICAgICBtZW1zZXQodFswXS5nbywgMjU1LCBzaXplb2YgdFswXS5nbyk7CiAgICAgICAgICAgICAgICBzeiA9IDE7CiAgICAgICAgfQoKICAgICAgICB2b2lkIGFkZF9zdHJpbmcgKGNvbnN0IHN0ZDo6c3RyaW5nJiBzKSB7CiAgICAgICAgICAgICAgICBpbnQgdiA9IDA7CiAgICAgICAgICAgICAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IHMubGVuZ3RoKCk7ICsraSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2hhciBjID0gc1tpXS0nYSc7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0W3ZdLm5leHRbY10gPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZW1zZXQgKHRbc3pdLm5leHQsIDI1NSwgc2l6ZW9mIHRbc3pdLm5leHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lbXNldCAodFtzel0uZ28sIDI1NSwgc2l6ZW9mIHRbc3pdLmdvKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0W3N6XS5saW5rID0gLTE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFtzel0ucCA9IHY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFtzel0ucGNoID0gYzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0W3N6XS5sZWFmID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFtzel0ub3V0ID0gLTE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFt2XS5uZXh0W2NdID0gc3orKzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB2ID0gdFt2XS5uZXh0W2NdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdFt2XS5sZWFmID0gdHJ1ZTsKCiAgICAgICAgICAgICAgICBrZXlzLnB1c2hfYmFjayhzKTsKICAgICAgICAgICAgICAgIHRbdl0ua2V5X2lkeCA9IGtleXMuc2l6ZSgpIC0gMTsKICAgICAgICB9CgogICAgICAgIGludCBnZXRfbGluayhpbnQgdikgewogICAgICAgICAgICAgICAgaWYgKHRbdl0ubGluayA9PSAtMSkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHYgPT0gMCB8fCB0W3ZdLnAgPT0gMCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0W3ZdLmxpbmsgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFt2XS5saW5rID0gZ28oZ2V0X2xpbmsodFt2XS5wKSwgdFt2XS5wY2gpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRbdl0ubGluazsKICAgICAgICB9CgogICAgICAgIGludCBnbyhpbnQgdiwgY2hhciBjKSB7CiAgICAgICAgICAgICAgICBpZih0W3ZdLmdvW2NdID09IC0xKQogICAgICAgICAgICAgICAgICAgICAgICBpZih0W3ZdLm5leHRbY10gIT0gLTEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFt2XS5nb1tjXSA9IHRbdl0ubmV4dFtjXTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRbdl0uZ29bY10gPSB2PT0wID8gMCA6IGdvKGdldF9saW5rKHYpLCBjKTsKICAgICAgICAgICAgICAgIHJldHVybiB0W3ZdLmdvW2NdOwogICAgICAgIH0KCiAgICAgICAgaW50IG91dChpbnQgdikKICAgICAgICB7CiAgICAgICAgICAgICAgICBpZih0W3ZdLm91dCA9PSAtMSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaW50IHUgPSBnZXRfbGluayh2KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYodFt1XS5sZWFmKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRbdl0ub3V0ID0gdTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih1ID09IDApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFt2XS5vdXQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdFt2XS5vdXQgPSBvdXQodSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgcmV0dXJuIHRbdl0ub3V0OwogICAgICAgIH0KCiAgICAgICAgdm9pZCBjaGVjayhpbnQgdiwgaW50IGkpCiAgICAgICAgewogICAgICAgICAgICAgICAgZm9yKGludCB1ID0gdjsgdiAhPSAwOyB2ID0gb3V0KHYpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZih0W3VdLmxlYWYpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgayA9IHRbdV0ua2V5X2lkeDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OmNvdXQgPDwgKGkgLSBrZXlzW2tdLmxlbmd0aCgpICsgMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPDwgIiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw8IGtleXNba10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPDwgc3RkOjplbmRsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2b2lkIGNoZWNrMihpbnQgdiwgaW50IGkpCiAgICAgICAgewogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBpZih0W3ZdLmxlYWYpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgayA9IHRbdl0ua2V5X2lkeDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OmNvdXQgPDwgKGkgLSBrZXlzW2tdLmxlbmd0aCgpICsgMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPDwgIiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw8IGtleXNba10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPDwgc3RkOjplbmRsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2b2lkIGZpbmRfYWxsX29jY3VycmVuY2VzKGNvbnN0IHN0ZDo6c3RyaW5nJiB0ZXh0KQogICAgICAgIHsKICAgICAgICAgICAgICAgIGludCB2ID0gMDsKICAgICAgICAgICAgICAgIGZvcihpbnQgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aCgpOyArK2kpCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIHYgPSBnbyh2LCB0ZXh0W2ldIC0gJ2EnKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2sodiwgaSArIDEpOwogICAgICAgICAgICAgICAgfQogICAgICAgIH0KCgpwcml2YXRlOgogICAgICAgIHZlcnRleDxLPiB0W05NQVgrMV07CiAgICAgICAgaW50IHN6OwogICAgICAgIHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiBrZXlzOwp9OwoKLy8KLy9jbGFzcyBTb2x1dGlvbiB7Ci8vcHVibGljOgovLyAgICAgICAgc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IHdvcmRCcmVhayhzdGQ6OnN0cmluZyBzLAovLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIHdvcmREaWN0KSB7Ci8vCi8vCi8vICAgICAgICB9Ci8vfTsKCnZvaWQgX3Rlc3RfMSgpCnsKICAgICAgICBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4gZGljdCA9IHsiYXBwbGUiLCAicGVuIiwgImFwcGxlcGVuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGluZSIsICJwaW5lYXBwbGUifTsKCiAgICAgICAgc3RkOjpzdHJpbmcgcyA9ICJwaW5lYXBwbGVwZW5hcHBsZSI7CgoKICAgICAgICBhdXRvbWF0b248PiBtOwoKICAgICAgICBmb3IoY29uc3QgYXV0byYgayA6IGRpY3QpCiAgICAgICAgICAgICAgICBtLmFkZF9zdHJpbmcoayk7CgogICAgICAgIG0uZmluZF9hbGxfb2NjdXJyZW5jZXMocyk7Cn0KCnZvaWQgX3Rlc3RfMigpCnsKICAgICAgICBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4gZGljdCA9IHsiYWJjIiwgImJjZGMiLCAiY2NjYiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJjZGQiLCAiYmJiYyJ9OwoKICAgICAgICBzdGQ6OnN0cmluZyBzID0gImFiY2RjYmNkZGJiYmNjY2JiYmNjY2JiIjsKCgogICAgICAgIGF1dG9tYXRvbjw+IG07CgogICAgICAgIGZvcihjb25zdCBhdXRvJiBrIDogZGljdCkKICAgICAgICAgICAgICAgIG0uYWRkX3N0cmluZyhrKTsKCiAgICAgICAgbS5maW5kX2FsbF9vY2N1cnJlbmNlcyhzKTsKfQoKaW50IG1haW4oKQp7CglzdGQ6OmNvdXQ8PCJUZXN0IDE6Ijw8c3RkOjplbmRsOwoJX3Rlc3RfMSgpOwoJc3RkOjpjb3V0PDwiVGVzdCAyOiI8PHN0ZDo6ZW5kbDsKCV90ZXN0XzIoKTsKCQoJcmV0dXJuIDA7Cn0=