#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define MAX_LENGTH 2000000
#define HASH_SIZE1 100021
#define HASH_BASE1 256
#define HASH_SIZE2 100007
#define HASH_BASE2 256
char str[MAX_LENGTH + 1];
int strLength;
char pattern[MAX_LENGTH + 1];
int patternLength;
void eraseNewLine(char str[], int& length) {
if (str[length - 1] == '\n')
str[--length] = 0;
}
int lgput(int a, int n, int mod) {
int p;
p = 1;
while (n) {
if (n & 1)
p = (long long)p * a % mod;
a = (long long)a * a % mod;
n >>= 1;
}
return p;
}
bool cmp(char str[], char pattern[]) {
int i;
i = 0;
while (str[i] && pattern[i] && str[i] == pattern[i])
++i;
return pattern[i] == 0;
}
int computeHash(char str[], int length, int hashBase, int hashSize) {
int hash, i;
hash = 0;
i = 0;
while (i < length) {
hash = (hash * hashBase + str[i]) % hashSize;
++i;
}
return hash;
}
int addToHash(int hash, char ch, int hashBase, int hashSize) {
return (hash * hashBase + ch) % hashSize;
}
int removeFromHash(int hash, char ch, int power, int hashSize) {
hash -= ch * power % hashSize;
if (hash < 0)
hash += hashSize;
return hash;
}
int computeHash1(char str[], int length) {
return computeHash(str, length, HASH_BASE1, HASH_SIZE1);
}
int computeHash2(char str[], int length) {
return computeHash(str, length, HASH_BASE2, HASH_SIZE2);
}
int addToHash1(int hash, char ch) {
return addToHash(hash, ch, HASH_BASE1, HASH_SIZE1);
}
int addToHash2(int hash, char ch) {
return addToHash(hash, ch, HASH_BASE2, HASH_SIZE2);
}
int removeFromHash1(int hash, char ch, int power) {
return removeFromHash(hash, ch, power, HASH_SIZE1);
}
int removeFromHash2(int hash, char ch, int power) {
return removeFromHash(hash, ch, power, HASH_SIZE2);
}
bool search(char str[], int strLength, char pattern[], int patternLength) {
int i;
int patternHash1, strHash1, power1;
int patternHash2, strHash2, power2;
bool patternFound;
patternHash1 = computeHash1(pattern, patternLength);
strHash1 = computeHash1(str, patternLength - 1);
power1 = lgput(HASH_BASE1, patternLength - 1, HASH_SIZE1);
patternHash2 = computeHash2(pattern, patternLength);
strHash2 = computeHash2(str, patternLength - 1);
power2 = lgput(HASH_BASE2, patternLength - 1, HASH_SIZE2);
patternFound = false;
i = patternLength;
while (i <= strLength && !patternFound) {
strHash1 = addToHash1(strHash1, str[i - 1]);
strHash2 = addToHash2(strHash2, str[i - 1]);
patternFound =
patternHash1 == strHash1 &&
patternHash2 == strHash2 &&
cmp(str + i - patternLength, pattern);
strHash1 = removeFromHash1(strHash1, str[i - patternLength], power1);
strHash2 = removeFromHash1(strHash2, str[i - patternLength], power2);
++i;
}
return patternFound;
}
void searchAndPrint(FILE* fout, char str[], int strLength, char pattern[], int patternLength) {
int i;
int patternHash1, strHash1, power1;
int patternHash2, strHash2, power2;
bool patternFound;
vector<int> matchesFound;
int noMatchesFound;
patternHash1 = computeHash(pattern, patternLength, HASH_BASE1, HASH_SIZE1);
strHash1 = computeHash(str, patternLength - 1, HASH_BASE1, HASH_SIZE1);
power1 = lgput(HASH_BASE1, patternLength - 1, HASH_SIZE1);
patternHash2 = computeHash(pattern, patternLength, HASH_BASE2, HASH_SIZE2);
strHash2 = computeHash(str, patternLength - 1, HASH_BASE2, HASH_SIZE2);
power2 = lgput(HASH_BASE2, patternLength - 1, HASH_SIZE2);
noMatchesFound = 0;
i = patternLength;
while (i <= strLength) {
strHash1 = addToHash(strHash1, str[i - 1], HASH_BASE1, HASH_SIZE1);
strHash2 = addToHash(strHash2, str[i - 1], HASH_BASE2, HASH_SIZE2);
patternFound =
patternHash1 == strHash1 &&
patternHash2 == strHash2 &&
cmp(str + i - patternLength, pattern);
if (patternFound) {
++noMatchesFound;
if (matchesFound.size() < 1000)
matchesFound.push_back(i - patternLength);
}
strHash1 = removeFromHash(strHash1, str[i - patternLength], power1, HASH_SIZE1);
strHash2 = removeFromHash(strHash2, str[i - patternLength], power2, HASH_SIZE2);
++i;
}
fprintf(fout, "%d\n", noMatchesFound);
for (auto match : matchesFound)
fprintf(fout, "%d ", match);
}
int main() {
FILE *fin, *fout;
fin = fopen("strmatch.in", "r");
fout = fopen("strmatch.out", "w");
fgets(pattern, sizeof(pattern), fin);
patternLength = strlen(pattern);
eraseNewLine(pattern, patternLength);
fgets(str, sizeof(str), fin);
strLength = strlen(str);
eraseNewLine(str, strLength);
//fprintf(fout, "%d\n", search(str, strLength, pattern, patternLength));
searchAndPrint(fout, str, strLength, pattern, patternLength);
fclose(fin);
fclose(fout);
return 0;
}