Pagini recente » Cod sursa (job #2960003) | Cod sursa (job #1774948) | Cod sursa (job #1587340) | Cod sursa (job #2460432) | Cod sursa (job #883006)
Cod sursa(job #883006)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>
using namespace std;
ifstream f("substr.in");
ofstream g("substr.out");
#define nmax (1<<14)+4
#define Logmax 16
#define ll long long
int n, K, Poz[Logmax][nmax];
typedef struct {
int a, b, poz;
}camp;
camp L[nmax];
int Rez[nmax], Prefix[nmax];
deque<int> dq;
//string S;
char S[nmax];
void citeste(){
f >> n >> K;
//f.get(); getline(f, S);
f.getline(S, nmax);
f.getline(S, nmax);
}
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(){
for(int i=0; i<n; ++i){
Poz[0][i+1] = cod(i);
}
int lim = 1; // primul 2^lim >= n;
for(; 1<<lim < n; ++lim);
// acum 1<<lim >= n;
for(int k=1; k<=lim; ++k){
for(int i=1; i<=n; ++i){
L[i].a = Poz[k-1][i];
int newI = i + (1<<(k-1));
if (newI > n) L[i].b = -1000;
else L[i].b = Poz[k-1][newI];
L[i].poz = i;
}
sort( L+1, L+n+1, cmp );
Poz[ k ][ L[1].poz ] = 1;
for(int i=2; i<=n; ++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<=n; ++i){
Rez[ Poz[lim][i] ] = i;// al poz[lim][i] -lea sufix in ordine crescatoare e al i-lea sufix din sirul initial
}
}
inline int Cmlpc(int x){
int i = Rez[x]; int j = Rez[x-1];
//fac o cautare binara pe biti; adica imi construiesc rezultatul bit cu bit
int rez = 0;
for(int k=Logmax-1; k>=0 && i<=n && j<=n; --k){
if ( Poz[k][i] == Poz[k][j] && (i + (1<<k) <= n ) && (j + (1<<k) <= n) ){//daca prefixul de lungime 2^k e la fel ma duc mai daparte
rez += (1<<k); i += (1<<k); j += (1<<k);
}
}
return rez;
}
void bagaPrefixe(){
for(int i=2; i<=n; ++i){
// cel mai lung prefix dintre cuvintele Rez[i]...n; Rez[i-1]...n;
Prefix[i] = Cmlpc(i);
}
}
void rezolva(){
// dupace ce am sortate sufixele pentru feicare secventa de K sufixe vad care e cel mai lung prefix a acestor sufixe
// bag un suffix array iar apoi tin minte pentru fiecare sufix cel mai lung prefix dintre el si sufixul i-1;
// astfel pentru o secvnte de sufix [x,..y] fixata cel mai lung prefix va fi minimul de pe intervalul [x+1, ..y] =>
// raspunsul va fi maximul acestor minime
suffixArray();
bagaPrefixe();
// si acum bag pt fiecare secventa de k
if (K == 1){
g << n << "\n";
return;
}
for(int i=2; i<=K; ++i){
while( dq.size() && Prefix[dq.back()] >= Prefix[i]) dq.pop_back();
while( dq.size() && dq.front() + K -1 <= i) dq.pop_front();
dq.push_back( i );
}
int Max = 0;
if (dq.size()) Max = Prefix[ dq.front() ];
for(int i=K+1; i<=n; ++i){
while( dq.size() && Prefix[ dq.back() ] >= Prefix[i]) dq.pop_back();
while( dq.size() && dq.front() + K -1 <= i ) dq.pop_front();
dq.push_back(i);
Max = max(Max, Prefix[ dq.front() ]);
}
cout << Max << "\n";
g << Max << "\n";
}
int main(){
citeste();
rezolva();
f.close();
g.close();
return 0;
}