zoukankan      html  css  js  c++  java
  • hdu3518 后缀数组

     题意:求字符串中不重叠的出现至少2次的子串个数。如aaaa 子串有a aa,2个。

    普通的求出height[]数组,然后枚举所有的长度差。

    对于"baba"

    i   height[i]     串

    1      0    a

    2      1    aba

    3      0    ba

    4  2    baba

    对于可能的k(满足的差),从1开始枚举。对于k=1时,下面的ba baba也是满足的,所以不能直接返回。而是要在不同k的时候计算。

    #include<iostream>
    #include <string.h>
    #include<stdlib.h>
    #define LL long long
    using namespace std;
    #define maxn 1020
    int max(int x,int y)
    {return x>y?x:y;}
    int min(int x,int y)
    {return x<y?x:y;}
    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++;
        }
        return;
    }
    int Rank[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) Rank[sa[i]]=i;
        for(i=0;i<n;height[Rank[i++]]=k)
            for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
        return;
    }
    int r[maxn],sa[maxn];
    char s[maxn];
    int ok(int k,int n)
    {
        int i,j,ret=0;
        int maxx,minx;
        maxx=-1;
        minx=9999999;
        for(i=1;i<=n;i++)
        {
            if(height[i]>=k)//分组满足大于k的
            {
                maxx=max(maxx,sa[i]);
                minx=min(minx,sa[i]);
            }
            else 
            {
                if(maxx-minx>=k)//之前满足条件就要+1;
                    ret++;
                maxx=sa[i];
                minx=sa[i];
            }
        }
        if(maxx-minx>=k)
                ret++;
        return ret;
    }
    int main()
    {
        int i,j;
        while(cin>>s)
        {
            if(s[0]=='#')break;
            int len=strlen(s);
            for(i=0;i<len;i++)
                r[i]=s[i];
            r[len]=0;
            da(r,sa,len+1,123);
            calheight(r,sa,len);
            LL ans=0;
            for(i=1;i<len;i++)
            {
                ans+=ok(i,len);
            }
            /*for(i=0;i<=len;i++)
            {
                printf("%d %d
    ",height[i],sa[i]);
            }*/
            cout<<ans<<endl;
        }
    }
  • 相关阅读:
    在pos:a元素不设定宽度的情况下,他的最大宽度是受父元素的宽度所限制的。
    跳过权限检查,强制修改mysql密码
    IIS7.5 配置ASP+ACCESS使用环境(转)
    windows 2008配置运行PHP5.5.X
    Content encoding error问题解决方法
    ubuntu 中文显示乱码问题 (转)
    Ubuntu 12.04中文输入法的安装(zhuan)
    html5开发之viewport使用
    Windows/Linux 环境搭建Git服务器 + vs2012集成git
    Windows+VS+SVN实现版本控制
  • 原文地址:https://www.cnblogs.com/sweat123/p/4793263.html
Copyright © 2011-2022 走看看