- #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=