• hdu_3518_Boring counting(后缀数组)


    题目链接:hdu_3518_Boring counting

    题意:

    给你一个字符串,让你找不重叠且出现大于1次以上的字串个数

    题解:

    后缀数组height数组的应用,我们枚举字串的长度,然后将height数组分段,符合条件就ans++

    为什么要这样做,因为height数组存的是相邻排名后缀的最大前缀数,如果height的值大于等于我们枚举的长度len,

    那么有可能这一段存在有两个以上的该长度的字串,然后我们统计这个段的开头长度l和结束长度r,如果r-l>=len,说明这段必有

    大于一个以上的该长度的相同子串,因为我们每次都是枚举len,按len分的段,所以不会重复。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;++i)
     3 using namespace std;
     4 
     5 namespace suffixarray{
     6     #define FN(n) for(int i=0;i<n;i++)
     7     const int N =1E3+7;
     8     int rnk[N],sa[N],height[N],c[N];char s[N];
     9     void getsa(int n,int m,int *x=rnk,int *y=height){
    10         FN(m)c[i]=0;FN(n)c[x[i]=s[i]]++;FN(m)c[i+1]+=c[i];
    11         for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    12         for(int k=1,p;p=0,k<=n;k=p>=n?N:k<<1,m=p){
    13             for(int i=n-k;i<n;i++)y[p++]=i;
    14             FN(n)if(sa[i]>=k)y[p++]=sa[i]-k;
    15             FN(m)c[i]=0;FN(n)c[x[y[i]]]++;FN(m)c[i+1]+=c[i];
    16             for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
    17             swap(x,y),p=1,x[sa[0]]=0;
    18             for(int i=1;i<n;i++)
    19             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
    20         }
    21         FN(n)rnk[sa[i]]=i;
    22         for(int i=0,j,k=0;i<n-1;height[rnk[i++]]=k)
    23         for(k=k?k-1:k,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++);
    24     }
    25 }
    26 
    27 inline void upd(int &a,int b){if(a>b)a=b;}
    28 inline void upu(int &a,int b){if(a<b)a=b;}
    29 
    30 using namespace suffixarray;
    31 int main(){
    32     while(~scanf("%s",s))
    33     {
    34         if(s[0]=='#')break;
    35         int len=strlen(s),ans=0;
    36         getsa(len+1,128);
    37         F(i,1,len)
    38         {
    39             int l=len+1,r=0;
    40             F(j,1,len)
    41             {
    42                 if(height[j]>=i)upd(l,sa[j]),upu(r,sa[j]);
    43                 else
    44                 {
    45                     if(r-l>=i)ans++;
    46                     l=r=sa[j];
    47                 }
    48             }
    49             if(r-l>=i)ans++;
    50         }
    51         printf("%d
    ",ans);
    52     }
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    Linux之SSH详解
    Linux下的静态路由配置
    Linux之防火墙配置
    五、SQL 转换:Oracle 转 MySQL
    四、Oracle转Mysql总结
    三、MySQL 替代 Oracle 序列以及自增长处理
    二、MySQL 高级部分
    一、MySQL 基础
    15-1、常用类
    14-1、GUI
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5744647.html
Copyright © 2020-2023  润新知