#include <iostream>
#include <vector>
#include <string>
using namespace std;
// Hàm tính toán mảng LPS cho xâu B
vector<int> computeLPSArray(const string& B) {
int m = B.length();
vector<int> lps(m);
int len = 0; // Độ dài của tiền tố dài nhất
lps[0] = 0; // Giá trị khởi đầu luôn là 0
int i = 1;
while (i < m) {
if (B[i] == B[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
// Hàm tìm kiếm KMP
vector<int> KMPSearch(const string& A, const string& B) {
int n = A.length();
int m = B.length();
vector<int> lps = computeLPSArray(B);
vector<int> positions;
int i = 0, j = 0; // Con trỏ cho A và B
while (i < n) {
if (B[j] == A[i]) {
i++;
j++;
}
if (j == m) {
// Tìm thấy mẫu tại vị trí i - j
positions.push_back(i - j + 1); // Chỉ số 1-based
j = lps[j - 1];
} else if (i < n && B[j] != A[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return positions;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
string a;
string b;
cin >> a >> b;
vector<int> positions = KMPSearch(a, b);
for (int pos : positions) {
cout << pos << ' ';
}
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c3RyaW5nPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKLy8gSMOgbSB0w61uaCB0b8OhbiBt4bqjbmcgTFBTIGNobyB4w6J1IEIKdmVjdG9yPGludD4gY29tcHV0ZUxQU0FycmF5KGNvbnN0IHN0cmluZyYgQikgewogICAgaW50IG0gPSBCLmxlbmd0aCgpOwogICAgdmVjdG9yPGludD4gbHBzKG0pOwogICAgaW50IGxlbiA9IDA7IC8vIMSQ4buZIGTDoGkgY+G7p2EgdGnhu4FuIHThu5EgZMOgaSBuaOG6pXQKICAgIGxwc1swXSA9IDA7IC8vIEdpw6EgdHLhu4sga2jhu59pIMSR4bqndSBsdcO0biBsw6AgMAogICAgaW50IGkgPSAxOwoKICAgIHdoaWxlIChpIDwgbSkgewogICAgICAgIGlmIChCW2ldID09IEJbbGVuXSkgewogICAgICAgICAgICBsZW4rKzsKICAgICAgICAgICAgbHBzW2ldID0gbGVuOwogICAgICAgICAgICBpKys7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKGxlbiAhPSAwKSB7CiAgICAgICAgICAgICAgICBsZW4gPSBscHNbbGVuIC0gMV07CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBscHNbaV0gPSAwOwogICAgICAgICAgICAgICAgaSsrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGxwczsKfQoKLy8gSMOgbSB0w6xtIGtp4bq/bSBLTVAKdmVjdG9yPGludD4gS01QU2VhcmNoKGNvbnN0IHN0cmluZyYgQSwgY29uc3Qgc3RyaW5nJiBCKSB7CiAgICBpbnQgbiA9IEEubGVuZ3RoKCk7CiAgICBpbnQgbSA9IEIubGVuZ3RoKCk7CiAgICB2ZWN0b3I8aW50PiBscHMgPSBjb21wdXRlTFBTQXJyYXkoQik7CiAgICB2ZWN0b3I8aW50PiBwb3NpdGlvbnM7CgogICAgaW50IGkgPSAwLCBqID0gMDsgLy8gQ29uIHRy4buPIGNobyBBIHbDoCBCCiAgICB3aGlsZSAoaSA8IG4pIHsKICAgICAgICBpZiAoQltqXSA9PSBBW2ldKSB7CiAgICAgICAgICAgIGkrKzsKICAgICAgICAgICAgaisrOwogICAgICAgIH0KICAgICAgICBpZiAoaiA9PSBtKSB7CiAgICAgICAgICAgIC8vIFTDrG0gdGjhuqV5IG3huqt1IHThuqFpIHbhu4sgdHLDrSBpIC0gagogICAgICAgICAgICBwb3NpdGlvbnMucHVzaF9iYWNrKGkgLSBqICsgMSk7IC8vIENo4buJIHPhu5EgMS1iYXNlZAogICAgICAgICAgICBqID0gbHBzW2ogLSAxXTsKICAgICAgICB9IGVsc2UgaWYgKGkgPCBuICYmIEJbal0gIT0gQVtpXSkgewogICAgICAgICAgICBpZiAoaiAhPSAwKSB7CiAgICAgICAgICAgICAgICBqID0gbHBzW2ogLSAxXTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGkrKzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBwb3NpdGlvbnM7Cn0KCmludCBtYWluKCkgewogIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOwogIGNpbi50aWUobnVsbHB0cik7CiAgc3RyaW5nIGE7CiAgc3RyaW5nIGI7CiAgY2luID4+IGEgPj4gYjsKICB2ZWN0b3I8aW50PiBwb3NpdGlvbnMgPSBLTVBTZWFyY2goYSwgYik7CiAgZm9yIChpbnQgcG9zIDogcG9zaXRpb25zKSB7CiAgICBjb3V0IDw8IHBvcyA8PCAnICc7CiAgfQp9