#include <string>
#include <iostream>
#include <vector>
using namespace std;
template<typename A> void kmp(string const& sample, string const& text, A const& action) {
vector<size_t> prefix(sample.length());
size_t last_prefix = prefix[0] = 0;
for (size_t i=1; i<sample.length(); i++) {
while (last_prefix > 0 && sample[last_prefix] != sample[i])
last_prefix = prefix[last_prefix-1];
if (sample[last_prefix] == sample[i])
last_prefix++;
prefix[i] = last_prefix;
}
last_prefix = 0;
for (size_t i=0; i<text.length(); i++) {
while (last_prefix > 0 && sample[last_prefix] != text[i])
last_prefix = prefix[last_prefix-1];
if (sample[last_prefix] == text[i])
last_prefix++;
if (last_prefix == sample.length()) {
action(i + 1 - sample.length());
}
}
}
int main() {
string sample = "aabaa";
string text = "aabaabaaaabaabaaab";
kmp(sample, text, [&](size_t i){
cout << i << endl;
});
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlPHR5cGVuYW1lIEE+IHZvaWQga21wKHN0cmluZyBjb25zdCYgc2FtcGxlLCBzdHJpbmcgY29uc3QmIHRleHQsIEEgY29uc3QmIGFjdGlvbikgewoJdmVjdG9yPHNpemVfdD4gcHJlZml4KHNhbXBsZS5sZW5ndGgoKSk7CgoJc2l6ZV90IGxhc3RfcHJlZml4ID0gcHJlZml4WzBdID0gMDsKCWZvciAoc2l6ZV90IGk9MTsgaTxzYW1wbGUubGVuZ3RoKCk7IGkrKykgewoJCXdoaWxlIChsYXN0X3ByZWZpeCA+IDAgJiYgc2FtcGxlW2xhc3RfcHJlZml4XSAhPSBzYW1wbGVbaV0pCgkJCWxhc3RfcHJlZml4ID0gcHJlZml4W2xhc3RfcHJlZml4LTFdOwoJCQoJCWlmIChzYW1wbGVbbGFzdF9wcmVmaXhdID09IHNhbXBsZVtpXSkKCQkJbGFzdF9wcmVmaXgrKzsKCQkKCQlwcmVmaXhbaV0gPSBsYXN0X3ByZWZpeDsKCX0KCQoJbGFzdF9wcmVmaXggPSAwOwoJZm9yIChzaXplX3QgaT0wOyBpPHRleHQubGVuZ3RoKCk7IGkrKykgewoJCXdoaWxlIChsYXN0X3ByZWZpeCA+IDAgJiYgc2FtcGxlW2xhc3RfcHJlZml4XSAhPSB0ZXh0W2ldKQoJCQlsYXN0X3ByZWZpeCA9IHByZWZpeFtsYXN0X3ByZWZpeC0xXTsKCQkJCgkJaWYgKHNhbXBsZVtsYXN0X3ByZWZpeF0gPT0gdGV4dFtpXSkKCQkJbGFzdF9wcmVmaXgrKzsKCQkJCgkJaWYgKGxhc3RfcHJlZml4ID09IHNhbXBsZS5sZW5ndGgoKSkgewoJCQlhY3Rpb24oaSArIDEgLSBzYW1wbGUubGVuZ3RoKCkpOwoJCX0KCX0KfQoKaW50IG1haW4oKSB7CglzdHJpbmcgc2FtcGxlID0gImFhYmFhIjsKCXN0cmluZyB0ZXh0ID0gImFhYmFhYmFhYWFiYWFiYWFhYiI7CgkKCWttcChzYW1wbGUsIHRleHQsIFsmXShzaXplX3QgaSl7CgkJY291dCA8PCBpIDw8IGVuZGw7Cgl9KTsKfQ==