zoukankan      html  css  js  c++  java
  • hdu3518

    题解:

    后缀数组

    枚举长度为k(1<=k<=len/2)的满足要求的子串个数

    代码:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1010;
    char str[N];
    int wa[N],wb[N],wv[N],Ws[N],sa[N],Rank[N],height[N];
    int cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void da(const char *r,int *sa,int n,int m) 
    {
        int *x=wa,*y=wb,*t;
        for (int i=0;i<m;i++) Ws[i]=0;
        for (int i=0;i<n;i++) Ws[x[i]=r[i]]++;
        for (int i=1;i<m;i++) Ws[i]+=Ws[i-1];
        for (int i=n-1;i>=0;i--) sa[--Ws[x[i]]]=i;
        for (int j=1,p=1;p<n;j*=2,m=p)
         {
             p=0;
            for (int i=n-j;i<n;i++) y[p++]=i;
            for (int i=0;i<n;i++)
             if (sa[i]>=j) y[p++]=sa[i]-j;
            for (int i=0;i<n;i++) wv[i]=x[y[i]];
            for (int i=0;i<m;i++) Ws[i]=0;
            for (int i=0;i<n;i++) Ws[wv[i]]++;
            for (int i=1;i<m;i++) Ws[i]+=Ws[i-1];
            for (int i=n-1;i>=0;i--) sa[--Ws[wv[i]]]=y[i];
            swap(x,y);x[sa[0]]=0;p=1;
            for (int i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
         }
        return;
    }
    void calheight(const char *r,int *sa,int n)
    {
        int j,k=0;
        for (int i=1;i<=n;i++) Rank[sa[i]]=i;
        for (int 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 solve(int k,int len)
    {
        int maxx=0,minn=INT_MAX,ans=0;
        for (int i=1;i<=len;i++)
         {
            if (height[i]>=k)
             maxx=max(maxx,max(sa[i-1],sa[i])),minn=min(minn,min(sa[i-1],sa[i]));
             else
              {
                if (maxx-minn>=k) ans++;
                maxx=0,minn=INT_MAX;
              }
         }
        if (maxx-minn>=k)ans++;
        return ans;
    }
    int main()
    {
        while (~scanf("%s",str) && strcmp(str,"#")!=0)
         {
            int len=strlen(str);
            da(str,sa,len+1,130);
            calheight(str,sa,len);
            ll ans=0;
            for (int i=1;i<=len/2;i++)ans+=solve(i,len);
            printf("%d
    ",ans);
         }
        return 0;
    }
  • 相关阅读:
    java bigdecimal (java double也时会失真)
    图像二维频谱的理解
    设计模式:装饰器模式实现 固定类功能
    c# winform 技术提升
    c# 多态的美丽(虚方法、抽象、接口实现)
    5天玩转C#并行和多线程编程
    [C#防止反编译].NET 产品版权保护方案 (.NET源码加密保护)
    用Ngen指令加快C#程序的启动速度
    cmd 批处理制作
    c#程序打包、机器代码生成(Ngen.exe)
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8516215.html
Copyright © 2011-2022 走看看