zoukankan      html  css  js  c++  java
  • HDU 3518 Boring counting(后缀数组,字符处理)

    题目

    参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html

    题目描述:

    找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠)。

    解题报告:

    后缀数组即可解之。

    枚举字串长度h

    对于每一次的h,利用height数组,找出连续的height大于等于h的里面最左端和最右端得为之l和r。

    如果l + h - 1 < r的话,说明没有重叠,答案加1.

    O(n^2)复杂度。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    
    #define maxn 1010
    int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
    int cmp(int *r,int a,int b,int l)
    {return r[a]==r[b]&&r[a+l]==r[b+l];}
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++)ws[i]=0;
        for(i=0;i<n;i++)ws[x[i]=r[i]]++;
        for(i=1;i<m;i++)ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--)sa[--ws[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p)
        {
            for(p=0,i=n-j;i<n;i++)y[p++]=i;
            for(i=0;i<n;i++) 
                if(sa[i]>=j) 
                    y[p++]=sa[i]-j;
            for(i=0;i<n;i++)wv[i]=x[y[i]];
            for(i=0;i<m;i++)ws[i]=0;
            for(i=0;i<n;i++)ws[wv[i]]++;
            for(i=1;i<m;i++)ws[i]+=ws[i-1];
            for(i=n-1;i>=0;i--)sa[--ws[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
    }
    int rankk[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++)rankk[sa[i]]=i;
        for(i=0;i<n;height[rankk[i++]]=k)
            for(k?k--:0,j=sa[rankk[i]-1];r[i+k]==r[j+k];k++);
    }
    
    int main()
    {
        char s[1010];
        while(scanf("%s",s)!=EOF)
        {
            if(strcmp(s,"#")==0)break;
            int len=strlen(s);
            int r[1010],sa[1010];
    
            //又忘记初始化排名了
            for(int i=0;i<len;i++)r[i]=s[i];
            r[len]=0;//zui hou yi ge zui xiao ,ji shu pai xu de xu yao
    
            da(r,sa,len+1,130);
            calheight(r,sa,len);
            //mei ju chang du
            int nn=len/2;
            int ans=0,minn,maxx;
            for(int i=1;i<=nn;i++)
            {
                minn=1010,maxx=-1;
                for(int j=2;j<=len;j++)
                {
                    ////有字串会被重复计算,所以不能这么写 
                    //if(height[j]>=i)
                    //{
                    //    minn=min(sa[j],sa[j-1]);
                    //    maxx=max(sa[j],sa[j-1]);
                    //    if(minn+i<=maxx)ans++;
                    //}
                    
                    //好好观察height数组的特性,可以这么写来避免重复计算
                    if(height[j]>=i)
                    {
                        minn=min(minn,min(sa[j],sa[j-1]));
                        maxx=max(maxx,max(sa[j],sa[j-1]));
                    }
                    else 
                    {
                        if(minn+i<=maxx)ans++;
                        minn=1010,maxx=-1;
                    }
                }
                if(minn+i<=maxx)ans++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    PHP学习—Cookie&Session
    IP组播综合实验
    k8s kubeadm部署高可用集群
    python调用zbbix的api实现批量添加域名监控脚本
    Python调用Harbor api删除私有仓库harbor镜像
    Kubernetes故障排查指南-分析容器退出状态码
    blackbox_exporter+grafana+prometheus监控主机存活,端口存活及网站状态
    k8s中使用ceph-csi在ceph中进行数据持久化
    Jenkins+K8S流水线自动化部署Java程序
    生产环境k8s中使用helm部署prometheus+grafana监控k8s集群中相关node和pod
  • 原文地址:https://www.cnblogs.com/laiba2004/p/3924136.html
Copyright © 2011-2022 走看看