Pagini recente » Cod sursa (job #2960948) | Cod sursa (job #3173345) | Cod sursa (job #1144844) | Cod sursa (job #771366) | Cod sursa (job #3287008)
//asta cica se cheama z
//vreau sa aflu de cate ori apare un prefix intr un vector v
//fie z[i] = lungimea maxima pt care [1, z[i]] == [i, i + z[i] - 1]
//si [l, r] un interval cu R maxim pentru care [1, r - l + 1] == [l, r] == z[l], pentru ca cu determinarea astora o sa te ocupi
//daca i pentru care vreau sa calculez z[i] > r, atunci fa brut si ia l = i
//cealata situatie este i apartine [l, r]
//atunci, fie k = i - l + 1 lungimea intervalului [l, i]
//avem ca z[i] >= min(z[k], r - i + 1), pentru ca minimul este lungimea pt care stim sigur ca v[k...] == v[i + k - 1...]
//exista doua situatii acum
//z[k] < r - i + 1, deci diferenta apare in intervalul [1, r - l + 1], pe care l am verificat
//caz in care e clar ca nu mai am nimic de facut decat sa avansez cu i
//si z[k] >= r - i + 1, in care nu mai stiu nimic despre unde apare diferenta
//asa ca faci brut
//numai ca de data asta iei l = i, ca sa foloseti faptul ca stii ca v[k, r - l + 1] == v[i, r]
#include <fstream>
#include <vector>
using namespace std;
ifstream cin("strmatch.in");
ofstream cout("strmatch.out");
const int NMAX = 2e6;
char v[2 * NMAX + 2];
int z[2 * NMAX + 2];
int main() {
int n = 0, m;
while (cin.get(v[++n]))
if (v[n] == '\n')
m = n - 1;
n--;
int l = 0, r = 0; //nu le initalizezi cu 1, n pt ca ideea e ca l, r se calculeaza pe masura ce mergi cu i
z[1] = n;
for (int i = 2; i <= n; i++) {
if (i > r) {
l = i, r = l - 1;
while (r + 1 <= n && v[(r + 1) - l + 1] == v[r + 1])
r++;
z[i] = r - l + 1;
}
else {
int k = i - l + 1;
if (z[k] < r - i + 1)
z[i] = z[k];
else {
l = i;
while (r + 1 <= n && v[(r + 1) - l + 1] == v[r + 1])
r++;
z[i] = r - l + 1;
}
}
}
vector<int> occurences;
for (int i = 2 * m + 1; i <= n; i++)
if (z[i] >= m)
occurences.push_back(i - m - 2);
cout << occurences.size() << '\n';
for (auto o : occurences)
cout << o << ' ';
}