Pagini recente » Cod sursa (job #2819208) | Cod sursa (job #295256) | Cod sursa (job #910462) | Cod sursa (job #649653) | Cod sursa (job #2391951)
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <cstring>
using namespace std;
#define MAX_LEN 4 * 500000
int size;
char pattern[MAX_LEN + 2];
char haystack[MAX_LEN + 2];
int z[MAX_LEN + 1];
int MAX(int X, int Y) {
return X > Y ? X : Y;
}
int MIN(int X, int Y) {
return X < Y ? X : Y;
}
void Z(char *s, int len) {
int i, l = 0, r = 0;
z[0] = 0;
for (i = 1; i < len; i++) {
z[i] = (MIN(z[i - l], r - i + 1) & -(i <= r));
while (s[z[i]] == s[z[i] + i]) {
z[i]++;
}
if (i + z[i] - 1 > r) {
r = i + z[i] - 1;
l = i;
}
}
}
/* Computing of the maximal suffix for <= */
int maxSuf(char *x, int m, int *p) {
int ms, j, k;
char a, b;
ms = -1;
j = 0;
k = *p = 1;
while (j + k < m) {
a = x[j + k];
b = x[ms + k];
if (a < b) {
j += k;
k = 1;
*p = j - ms;
}
else
if (a == b)
if (k != *p)
++k;
else {
j += *p;
k = 1;
}
else { /* a > b */
ms = j;
j = ms + 1;
k = *p = 1;
}
}
return ms;
}
/* Computing of the maximal suffix for >= */
int maxSufTilde(char *x, int m, int *p) {
int ms, j, k;
char a, b;
ms = -1;
j = 0;
k = *p = 1;
while (j + k < m) {
a = x[j + k];
b = x[ms + k];
if (a > b) {
j += k;
k = 1;
*p = j - ms;
}
else
if (a == b)
if (k != *p)
++k;
else {
j += *p;
k = 1;
}
else { /* a < b */
ms = j;
j = ms + 1;
k = *p = 1;
}
}
return ms;
}
int choose(int lim) {
int remained = 1;
while (remained < size && z[remained] < lim) {
remained++;
}
if (remained < size)
return z[remained];
else
return z[size - 1];
}
static vector<int> twoWaySearchImpl(char* haystack, int haystacklen, char* needle, int needlelen) {
int i, j, maxSuffix, memory, p, period, q;
//int matches = 0;
int lastMatch = 0;
/* Preprocessing */
i = maxSuf(needle, needlelen, &p);
/*j = maxSufTilde(needle, needlelen, &q);
std::cerr << "1: " << p << " and " << i << endl;
std::cerr << "2: " << q << " and " << j << endl;
if (i > j) {
maxSuffix = i;
period = p;
}
else {
maxSuffix = j;
period = q;
}
*/
maxSuffix = i;
period = p;
vector<int> matches;
Z(needle, needlelen);
size = 1;
for (int i = 1; i < needlelen; i++) {
if (z[i] + i == needlelen) {
z[size++] = i;
}
}
z[size++] = needlelen;
/*
std::cerr << "Z values\n";
for (int i = 1; i < size; i++)
std:: cerr << z[i] << " ";
std:: cerr << "\n";
*/
//std::cerr << "period von ihnen = " << period << endl;
//assert(period == z[1]);
/* Searching */
/*if (memcmp(needle, needle + period, maxSuffix + 1) == 0) {
j = 0;
memory = -1;
while (j <= haystacklen - needlelen) {
i = MAX(maxSuffix, memory) + 1;
while (i < needlelen && needle[i] == haystack[i + j])
++i;
if (i >= needlelen) {
i = maxSuffix;
while (i > memory && needle[i] == haystack[i + j])
--i;
if (i <= memory)
matches++;
j += period;
memory = needlelen - period - 1;
}
else {
j += (i - maxSuffix);
memory = -1;
}
}
}
else {*/
//std::cerr << "enters here\n";
//period = MAX(maxSuffix + 1, needlelen - maxSuffix - 1) + 1;
j = 0;
//std::cerr << "period danach " << period << " und maxSuffix = " << maxSuffix << endl;
while (j <= haystacklen - needlelen) {
i = maxSuffix + 1;
while (i < needlelen && needle[i] == haystack[i + j])
++i;
if (i >= needlelen) {
//std::cerr << "partial match at " << (j + maxSuffix + 1) << endl;
int lim = MAX(j, lastMatch) - j;
i = maxSuffix;
while (i >= lim && needle[i] == haystack[i + j])
--i;
//std::cerr << "lastMatch = " << lastMatch << " j = " << j << endl;
//std::cerr << "lim = " << lim << " and stops at " << i << "\n";
if (i < lim) {
//std::cerr << "was";
matches.push_back(j);
}
lastMatch = j + needlelen;
j += period;
}
else {
j += i - maxSuffix;
if (j < lastMatch) {
j = lastMatch - needlelen + choose(j - lastMatch + needlelen);
}
}
}
return matches;
}
int main(void) {
ifstream cin("strmatch.in");
ofstream cout("strmatch.out");
int N, Q;
//cin >> N >> Q >> haystack;
cin >> pattern >> haystack;
vector<int> matches = twoWaySearchImpl(haystack, strlen(haystack), pattern, strlen(pattern));
/*std::cerr << haystack << endl;
while (Q--) {
cin >> pattern;
cout << twoWaySearchImpl(haystack, N, pattern, strlen(pattern)) << "\n";
}*/
cout << matches.size() << "\n";
for (int i = 0; i < matches.size() && i < 1000; i++)
cout << matches[i] << " ";
cout << "\n";
return 0;
}