zoukankan      html  css  js  c++  java
  • poj 3261 Milk Patterns

    http://poj.org/problem?id=3261

    题意:

    求可重复的最长出现k次子串

    后缀数组求出height后分组

    从大到小每句长度,并查集合并

    #include<cstdio>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    
    #define N 20001
    
    using namespace std;
    
    int n,m,tot;
    int a[N],has[N];
    
    int v[N];
    int p=0,q=1;
    int sa[2][N],rk[2][N],height[N];
    
    int fa[N],siz[N];
    
    vector<int>V[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void mul(int k,int *sa,int *rk,int *SA,int *RK)
    {
        for(int i=1;i<=n;++i) v[rk[sa[i]]]=i;
        for(int i=n;i;--i) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;
        for(int i=n-k+1;i<=n;++i) SA[v[rk[i]]--]=i;
        for(int i=1;i<=n;++i) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
    }
    
    void presa()
    {
        for(int i=1;i<=n;++i) v[a[i]]++;
        for(int i=1;i<=tot;++i) v[i]+=v[i-1];
        for(int i=1;i<=n;++i) sa[p][v[a[i]]--]=i;
        for(int i=1;i<=n;++i) rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
        for(int k=1;k<n;k<<=1,swap(p,q)) 
        mul(k,sa[p],rk[p],sa[q],rk[q]);    
    }
    
    void get_height()
    {
        int j;
        for(int i=1,k=0;i<=n;++i)
        {
            j=sa[p][rk[p][i]-1];
            while(a[i+k]==a[j+k]) k++;
            height[rk[p][i]]=k;
            if(k) k--;
        }
    }
    
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    
    void unionn(int u,int v)
    {
        u=find(u);
        v=find(v);
        siz[v]+=siz[u];
        fa[u]=v;
    }
    
    void solve()
    {
        for(int i=1;i<=n;++i) fa[i]=i,siz[i]=1;
        for(int i=2;i<=n;++i) V[height[i]].push_back(i);
        int w,s;
        for(int i=n;i;--i)
        {
            s=V[i].size();
            if(!s) continue;
            for(int j=0;j<s;++j) 
            {
                w=V[i][j];
                if(find(sa[p][w-1])!=find(sa[p][w])) unionn(sa[p][w-1],sa[p][w]);
                if(w<n && height[w+1]>=i && find(sa[p][w+1])!=find(sa[p][w])) unionn(sa[p][w+1],sa[p][w]);
                if(siz[find(sa[p][w])]>=m) 
                {
                    printf("%d",i);
                    return;
                }
            }
        }    
    }
    
    int main()
    {
        read(n); read(m);
        for(int i=1;i<=n;++i) read(a[i]),has[i]=a[i];
        sort(has+1,has+n+1);
        tot=unique(has+1,has+n+1)-has-1;
        for(int i=1;i<=n;++i) a[i]=lower_bound(has+1,has+tot+1,a[i])-has;
        presa();
        get_height();
        solve();
        return 0;
    }
  • 相关阅读:
    IT小小鸟读后感
    关于C语言的问卷调查
    (学习进度表)【第六周】
    (学习进度表)【第五周】
    作业二(过早的放弃是失败的根源)
    读《世界是数字的》笔记
    作业3(学习进度表)【第四周】
    作业1
    读《我是一只IT小小鸟》笔记
    价值观作业
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8507344.html
Copyright © 2011-2022 走看看