#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Knuth-Morris-Pratt Algorithm
// bush의 앞에서부터 needle의 최초 위치를 찾아 반환합니다.
size_t kmp(const string& bush, const string& needle)
{
const size_t needleLen = needle.length();
const size_t bushLen = bush.length();
// string::find는 패턴 문자열이 비어있을 경우 0을 반환함.
if (needleLen == 0)
{
return 0;
}
// pi[match] == needle[:match+1]의 최대 동일 접두접미사 길이
vector<size_t> pi(needleLen, 0ul);
for (size_t i = 1, match = 0; i < needleLen; ++i)
{
while (match > 0 && needle[i] != needle[match])
match = pi[match - 1];
if (needle[i] == needle[match])
pi[i] = ++match;
}
for (size_t i = 0, match = 0; i < bushLen; ++i)
{
// 매치 실패시
// 성공할 때까지 혹은 더 이상 할 수 없을 때까지 건너뛰기 시도.
while (match > 0 && bush[i] != needle[match])
{
match = pi[match - 1];
}
// 매치 성공시
// 다음 문자 검색 준비.
// 다음 문자가 없다면 검색이 완료된 것이므로 위치 계산 후 반환.
if (bush[i] == needle[match])
{
++match;
if (match >= needleLen)
{
// i를 반환하지 않고 이러는 이유는
// 현재 i가 검색된 문자열의 뒤를 가리키고 있기 때문임.
return i - (match - 1);
}
}
}
// 찾을 수 없음.
return string::npos;
}
int main()
{
string bush;
string needle;
getline(cin, bush);
getline(cin, needle);
size_t index = kmp(bush, needle);
size_t answer = bush.find(needle);
// 구현 검증
if (answer != index)
{
cout << "FAIL! Answer : " << answer << ", Me : " << index << endl;
return -1;
}
if (index == string::npos)
{
cout << "Couldn't find!" << endl;
}
else
{
cout << "Index : " << index << endl;
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCi8vIEtudXRoLU1vcnJpcy1QcmF0dCBBbGdvcml0aG0KLy8gYnVzaOydmCDslZ7sl5DshJzrtoDthLAgbmVlZGxl7J2YIOy1nOy0iCDsnITsuZjrpbwg7LC+7JWEIOuwmO2ZmO2VqeuLiOuLpC4Kc2l6ZV90IGttcChjb25zdCBzdHJpbmcmIGJ1c2gsIGNvbnN0IHN0cmluZyYgbmVlZGxlKQp7CiAgICBjb25zdCBzaXplX3QgbmVlZGxlTGVuID0gbmVlZGxlLmxlbmd0aCgpOwogICAgY29uc3Qgc2l6ZV90IGJ1c2hMZW4gPSBidXNoLmxlbmd0aCgpOwogICAgCiAgICAvLyBzdHJpbmc6OmZpbmTripQg7Yyo7YS0IOusuOyekOyXtOydtCDruYTslrTsnojsnYQg6rK97JqwIDDsnYQg67CY7ZmY7ZWoLgogICAgaWYgKG5lZWRsZUxlbiA9PSAwKQogICAgewogICAgICAgIHJldHVybiAwOwogICAgfQoKCiAgICAvLyBwaVttYXRjaF0gPT0gbmVlZGxlWzptYXRjaCsxXeydmCDstZzrjIAg64+Z7J28IOygkeuRkOygkeuvuOyCrCDquLjsnbQKICAgIHZlY3RvcjxzaXplX3Q+IHBpKG5lZWRsZUxlbiwgMHVsKTsKCiAgICBmb3IgKHNpemVfdCBpID0gMSwgbWF0Y2ggPSAwOyBpIDwgbmVlZGxlTGVuOyArK2kpCiAgICB7CiAgICAgICAgd2hpbGUgKG1hdGNoID4gMCAmJiBuZWVkbGVbaV0gIT0gbmVlZGxlW21hdGNoXSkKICAgICAgICAgICAgbWF0Y2ggPSBwaVttYXRjaCAtIDFdOwogICAgICAgIGlmIChuZWVkbGVbaV0gPT0gbmVlZGxlW21hdGNoXSkKICAgICAgICAgICAgcGlbaV0gPSArK21hdGNoOwogICAgfQogICAgCiAgICAKICAgIGZvciAoc2l6ZV90IGkgPSAwLCBtYXRjaCA9IDA7IGkgPCBidXNoTGVuOyArK2kpCiAgICB7CiAgICAgICAgLy8g66ek7LmYIOyLpO2MqOyLnAogICAgICAgIC8vIOyEseqzte2VoCDrlYzquYzsp4Ag7Zi57J2AIOuNlCDsnbTsg4Eg7ZWgIOyImCDsl4bsnYQg65WM6rmM7KeAIOqxtOuEiOubsOq4sCDsi5zrj4QuCiAgICAgICAgd2hpbGUgKG1hdGNoID4gMCAmJiBidXNoW2ldICE9IG5lZWRsZVttYXRjaF0pCiAgICAgICAgewogICAgICAgICAgICBtYXRjaCA9IHBpW21hdGNoIC0gMV07CiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8vIOunpOy5mCDshLHqs7Xsi5wKICAgICAgICAvLyDri6TsnYwg66y47J6QIOqygOyDiSDspIDruYQuCiAgICAgICAgLy8g64uk7J2MIOusuOyekOqwgCDsl4bri6TrqbQg6rKA7IOJ7J20IOyZhOujjOuQnCDqsoPsnbTrr4DroZwg7JyE7LmYIOqzhOyCsCDtm4Qg67CY7ZmYLgogICAgICAgIGlmIChidXNoW2ldID09IG5lZWRsZVttYXRjaF0pCiAgICAgICAgewogICAgICAgICAgICArK21hdGNoOwogICAgICAgICAgICBpZiAobWF0Y2ggPj0gbmVlZGxlTGVuKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBp66W8IOuwmO2ZmO2VmOyngCDslYrqs6Ag7J2065+s64qUIOydtOycoOuKlAogICAgICAgICAgICAgICAgLy8g7ZiE7J6sIGnqsIAg6rKA7IOJ65CcIOusuOyekOyXtOydmCDrkqTrpbwg6rCA66as7YKk6rOgIOyeiOq4sCDrlYzrrLjsnoQuCiAgICAgICAgICAgICAgICByZXR1cm4gaSAtIChtYXRjaCAtIDEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgCiAgICAKICAgIC8vIOywvuydhCDsiJgg7JeG7J2MLgogICAgcmV0dXJuIHN0cmluZzo6bnBvczsKfQoKaW50IG1haW4oKQp7CiAgICBzdHJpbmcgYnVzaDsKICAgIHN0cmluZyBuZWVkbGU7CiAgICAKICAgIGdldGxpbmUoY2luLCBidXNoKTsKICAgIGdldGxpbmUoY2luLCBuZWVkbGUpOwogICAgCiAgICBzaXplX3QgaW5kZXggPSBrbXAoYnVzaCwgbmVlZGxlKTsKICAgIHNpemVfdCBhbnN3ZXIgPSBidXNoLmZpbmQobmVlZGxlKTsKICAgIAogICAgLy8g6rWs7ZiEIOqygOymnQogICAgaWYgKGFuc3dlciAhPSBpbmRleCkKICAgIHsKICAgICAgICBjb3V0IDw8ICJGQUlMISBBbnN3ZXIgOiAiIDw8IGFuc3dlciA8PCAiLCBNZSA6ICIgPDwgaW5kZXggPDwgZW5kbDsKICAgICAgICByZXR1cm4gLTE7CiAgICB9CiAgICAKICAgIGlmIChpbmRleCA9PSBzdHJpbmc6Om5wb3MpCiAgICB7CiAgICAgICAgY291dCA8PCAiQ291bGRuJ3QgZmluZCEiIDw8IGVuZGw7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgY291dCA8PCAiSW5kZXggOiAiIDw8IGluZGV4IDw8IGVuZGw7CiAgICB9CiAgICAKICAgIHJldHVybiAwOwp9