zoukankan      html  css  js  c++  java
  • hdu 6194 string string string(后缀数组)

    题目链接:hdu 6194 string string string

    题意:

    给你一个字符串,给你一个k,问你有多少个子串恰好在原串中出现k次。

    题解:

    后缀数组求出sa后,用height数组的信息去找答案。

    每次用k长度的区间去卡height数组,求出该区间的lcp。

    该区间的贡献就是ans=lcp-max(height[i],height[i+k])。

    如果ans<=0,就不贡献。

    比如 2 aaa

    后缀数组为:

    1 a

    2 aa

    3 aaa

    height为 0,1,2

    现在扫到[1,2],lcp=1,max(height[i],height[i+k])=2,ans=-1,所以该区间没有贡献

    到[2,3],lcp=2,max(height[i],height[i+k])=1,ans=1,所以该区间贡献1。

     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 =1E5+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 using namespace suffixarray;
    27 
    28 int t,k,n,f[N][20];
    29 
    30 void rmq(int *a)
    31 {
    32     for(int i=1;i<=n;i++)f[i][0]=a[i];
    33     for(int j=1;1<<j<n;j++)for(int i=1;i<=n;i++)
    34     if(i+(1<<j)-1<=n)f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
    35     else break;
    36 }
    37 inline int find(int l,int r)
    38 {
    39     int k=31-__builtin_clz(r-l+1);
    40     return min(f[l][k],f[r-(1<<k)+1][k]);
    41 }
    42 
    43 int main()
    44 {
    45     scanf("%d",&t);
    46     while(t--)
    47     {
    48         scanf("%d%s",&k,s);
    49         n=strlen(s),getsa(n+1,300);
    50         height[n+1]=0;rmq(height);
    51         int ans=0;
    52         F(i,1,n)
    53         {
    54             if(i+k-1>n)continue;
    55             int lcp;
    56             if(i+1>i+k-1)lcp=n-sa[i];
    57             else lcp=find(i+1,i+k-1);
    58             lcp-=max(height[i],height[i+k]);
    59             if(lcp<=0)continue;
    60             ans+=lcp;
    61         }
    62         printf("%d
    ",ans);
    63     }
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    .netcore3.1——应用文档组件Swagger
    .netcore3.1——应用验证组件FluentValidation
    闲聊项目心得
    微软官方的.net系列文档
    一分钟了解Allegro导入DXF文件
    Altium Designer快速调整丝印
    Android探究之View的绘制流程
    项目管理探究之挣值管理常见计算
    Android探究之ANR
    基于深度学习时间序列预测系统项目需求分析心得
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7502153.html
Copyright © 2011-2022 走看看