Pagini recente » Cod sursa (job #1309919) | Cod sursa (job #1625374) | Cod sursa (job #2172509) | Cod sursa (job #972976) | Cod sursa (job #882656)
Cod sursa(job #882656)
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
ifstream f("substr.in");
ofstream g("substr.out");
#define nmax 16400
#define Logmax 15
string S;
int n, K;
int Poz[Logmax][nmax];
typedef struct{
int a, b, poz;
}camp;
camp L[nmax];
int Rez[nmax];
void citeste(){
f >> n >> K; f.get();
getline(f, S);
}
inline int cod(int x){
if (S[x] >= 'a' && S[x] <= 'z') return S[x] - 'a';
if (S[x] >= 'A' && S[x] <= 'Z') return S[x] - 'A' - 'a';
if (S[x] >= '0' && S[x] <= '9') return S[x] - '0' - 'a' - 'A';
}
bool cmp( camp A, camp B){
if (A.a == B.a) return A.b < B.b;
return A.a < B.a;
}
void suffixArray(){
int sz = S.size();
for(int i=0; i<S.size(); ++i){
Poz[0][i+1] = cod(i);
}
int lim = 1; // primul 2^lim >= sz;
for(; 1<<lim < sz; ++lim);
// acum 1<<lim >= sz;
for(int k=1; k<=lim; ++k){
for(int i=1; i<=sz; ++i){
L[i].a = Poz[k-1][i];
int newI = i + (1<<(k-1));
if (newI > sz) L[i].b = -1000;
else L[i].b = Poz[k-1][newI];
}
sort( L+1, L+sz+1, cmp );
Poz[ k ][ L[1].poz ] = 1;
for(int i=2; i<=sz; ++i){
if ( L[i].a == L[i-1].a && L[i].b == L[i-1].b)
Poz[k][ L[i].poz ] = Poz[k][ L[i-1].poz ];
else Poz[k][ L[i].poz ] = i;
}
}
for(int i=1; i<=sz; ++i){
Rez[ Poz[lim][i] ] = i;// al poz[lim][i] -lea sufix in ordine crescatoare e al i-lea sufix din sirul initial
}
for(int i=1; i<=sz; ++i){
cout << Rez[i] << "\n";
for(int j=Rez[i]; j<=S.size(); ++j){
g << S[j-1];
}
g << "\n";
}
}
inline int cbSt(int x, int y){
// ultimul mai mic ca si mine
int st = 0; int dr = n+1;
while(dr - st > 1){
int mij = (st + dr) / 2;
int ok = 0; // sunt la fel
// ok = 1; insemana ca mij=ul e < ca si mine
// ok = -1; insmena ca mij-ul >= ca si mine
for(int i=Rez[mij], j=x; j<=y && i<=S.size(); ++j, ++i){// j-ul e indexat corect; i-ul e indexat de la 1
if (S[i-1] == S[j]) continue;
if (S[i-1] < S[j]){ ok = 1; break;}
if (S[i-1] > S[j]){ ok = -1; break;}
}
int sz1 = S.size() - Rez[mij] + 1;// lungimea secventei Rez[mij]..S.size();
int sz2 = y -x + 1;// lungimea secventei fixate
if (ok == 0){
if (sz1 > sz2) ok = 1;
else ok = -1;
}
if (ok == 1){
st = mij;
}else dr = mij;
}
return st;
}
inline int cbDr(int x, int y){
int st = 0; int dr = n+1;
while(dr - st > 1){
int mij = (st + dr) / 2;
int ok = 0;
for(int i=Rez[mij], j=x; j<=y && i<=S.size(); ++j, ++i){
if (S[i-1] == S[j]) continue;
if (S[i-1] > S[j]){ ok =1; break;}
if (S[i-1] < S[j]){ ok = -1; break; }
}
int sz1 = S.size() - Rez[mij] + 1;// lungimea secventei Rez[mij]..S.size();
int sz2 = y -x + 1;// lungimea secventei fixate
if (ok == 0){
if ( sz1 > sz2 ) ok = 1;
else ok = -1;
}
if (ok == 1){
dr = mij;
}else st = mij;
}
return dr;
}
inline int apare(int x, int y){
// deci am secventa x..y vreau sa vad de cat ori apare
return ( cbDr(x, y) - cbSt(x, y) + 1 - 2 );
}
inline int cauta(int poz){
// caut cea mai mare secventa din secventa poz...n care apare de cel putin K ori
// la sfarsit va fi evident de genul poz..ceva
--poz;// e indexat de la 1 iar sirul de la 0
int st = poz-1; int dr = S.size();
while( dr - st > 1){
int mij = ( st + dr ) / 2;
//secventa poz...mij
if ( apare(poz, mij) >= K){
st = mij;
}else dr = mij;
}
return st;
}
void rezolva(){
// sortez sufixele iar apoi caut pentru fiecare sufix cea mai mare lungime care apare de cel putin K ori
suffixArray();
int Max = 0;
for(int i=1; i<=n; ++i){
Max = max(Max, cauta(i) );
}
cout << Max << "\n";
}
int main(){
citeste();
rezolva();
return 0;
}