Cod sursa(job #3149761)

Utilizator CelestinNegraru Celestin Celestin Data 11 septembrie 2023 23:43:34
Problema Substr Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.92 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
#define nmax 16390
#define logmax 15
using namespace std;
char s[nmax];
int dp[logmax][nmax];///dp[i][j]=pozitia prefixului de lungime 2^i ce incepe pe pozitia j in sirul subsecventelor de lungime 2^i sortate
struct aux{
    int poz;
    int r[2];
};
aux l[nmax];
struct sufix{
    int pozitie;
    int index;
};
sufix v[nmax];
int n,k,lg,ans;
ifstream f("substr.in");
ofstream g("substr.out");
bool cmp(aux A,aux B)
{
    if(A.r[0]==B.r[0])
        return A.r[1]<B.r[1];
    else return A.r[0]<B.r[0];
}
bool cmp2(sufix A,sufix B)
{
    return A.pozitie<B.pozitie;
}
int lcp(int i,int j)///lcp(i,j) returneaza lungimea celui mai lung prefix al sufixelor ce incep pe pozitiile i si j
{
    if(i==j)
        return n-i;
    int ans=0;
    for(int k=lg;k>=0&&i<n&&j<n;k--)
    {
        if(dp[k][i]==dp[k][j])
            i+=(1<<k),j+=(1<<k),ans+=(1<<k);
    }
    return ans;
}
int main()
{
    f>>n>>k;
    f>>s;
    for(int i=0;i<n;i++)
    {
        dp[0][i]=s[i]-'0';///oferim o ordine relativa, stiu ca nu e chiar pozitia corecta
    }
    for(int i=1,cnt=1;(1<<i)<(n<<1);i++,cnt<<=1)
    {
       for(int j=0;j<n;j++)
       {
           ///aici compunem prefixele sufixelor de lungime 2^k din prefixele de lungime 2^(k-1)
           l[j].r[0]=dp[i-1][j];
           l[j].r[1]=j+cnt<n?dp[i-1][j+cnt]:-1;///-1 pentru dolar gen daca iese din sir
           l[j].poz=j;///daca sortam vectorul avem nevoie de pozitii
       }
       sort(l,l+n,cmp);
       for(int j=0;j<n;j++)
       {
           dp[i][l[j].poz]=j>0&&l[j].r[0]==l[j-1].r[0]&&l[j].r[1]==l[j-1].r[1]?dp[i][l[j-1].poz]:j;
       }
    }
    for(lg=1;(1<<lg)<n;lg++);
    for(int i=0;i<n;i++)
        v[i].pozitie=dp[lg][i],v[i].index=i;
    sort(v,v+n,cmp2);
    for(int i=0;i<n-k+1;i++)
    {
        int pre=lcp(v[i].index,v[i+k-1].index);
        if(pre>ans)
            ans=pre;
    }
    g<<ans;
    return 0;
}