zoukankan      html  css  js  c++  java
  • 【UVA10829】 L-Gap Substrings (后缀数组)

    Description

    If a string is in the form UVU, where U is not empty, and V has exactly L characters, we say UVU
    is an L-Gap string. For example, abcbabc is a 1-Gap string. xyxyxyxyxy is both a 2-Gap string
    and also a 6-Gap string, but not a 10-Gap string (because U is non-empty).
    Given a string s, and a positive integer g, you are to find the number of g-Gap substrings in s. s
    contains lower-case letters only, and has at most 50,000 characters.

    Input
    The first line contains a single integer t (1 ≤ t ≤ 10), the number of test cases. Each of the t followings
    contains an integer g (1 ≤ g ≤ 10) followed by a string s.

    Output
    For each test case, print the case number and the number of g-Gap substrings. Look at the output for
    sample input for details.

    Sample Input
    2
    1 bbaabaaaaa
    5 abxxxxxab


    Sample Output
    Case 1: 7
    Case 2: 1

    【题意】

      UVU形式的串的个数,V的长度规定,U要一样,位置不一样即为不同字串

    【分析】

      表示做了poj3693还是不会做这题。

      为什么会想到枚举L然后分块呢????

      为什么呢????

      这种方法于我而言还是有点难理解的啊。

      主要是分块!!

      

    任意一个满足条件的UVU,假设U的长度是len,那么左端的U必然包含按照len切分的T串的某个字串,及0,len,2len,3len...。(这点要仔细想清楚)

    那么枚举每个端点i*len,然后利用RMQ求后缀i*len和后缀i*len+L+len的LCP,然后字符串T反向,再求一遍反向的LCP2。(其中LCP要小于等于len,否则会重复,仔细想清楚)

    最后累加求和sum+=(LCP+LCP2-1)-len+1。(这点想清楚为什么是-len)

    blog:http://blog.csdn.net/u011526463/article/details/14000693

      

      还有,其实,貌似不用后缀数组直接两个while前后就可以了。时间貌似还是nlogn的。  【(2017-03-24 14:43:33)许多年发现以前在搞笑。。

      

    代码如下:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxl 100010
      9 
     10 int l,len;
     11 char s[Maxl];
     12 int c[Maxl],cl;
     13 
     14 int mymin(int x,int y) {return x<y?x:y;}
     15 
     16 void init()
     17 {
     18     scanf("%d%s",&l,s);
     19     len=strlen(s);
     20     cl=0;
     21     for(int i=0;i<len;i++) c[++cl]=s[i]-'a'+1;
     22 }
     23 
     24 int sa[Maxl],rk[Maxl],y[Maxl],wr[Maxl],Rs[Maxl];
     25 void get_sa(int m)
     26 {
     27     memcpy(rk,c,sizeof(rk));
     28     for(int i=0;i<=m;i++) Rs[i]=0;
     29     for(int i=1;i<=cl;i++) Rs[rk[i]]++;
     30     for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
     31     for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i;
     32     
     33     int ln=1,p=0;
     34     while(p<cl)
     35     {
     36         int k=0;
     37         for(int i=cl-ln+1;i<=cl;i++) y[++k]=i;
     38         for(int i=1;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
     39         for(int i=1;i<=cl;i++) wr[i]=rk[y[i]];
     40         
     41         for(int i=0;i<=m;i++) Rs[i]=0;
     42         for(int i=1;i<=cl;i++) Rs[wr[i]]++;
     43         for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
     44         for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i];
     45         
     46         for(int i=1;i<=cl;i++) wr[i]=rk[i];
     47         for(int i=cl+1;i<=cl+ln;i++) wr[i]=0;
     48         p=1,rk[sa[1]]=1;
     49         for(int i=2;i<=cl;i++)
     50         {
     51             if(wr[sa[i]]!=wr[sa[i-1]]||wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++;
     52             rk[sa[i]]=p;
     53         }
     54         ln*=2,m=p;
     55     }
     56     sa[0]=rk[0]=0;
     57 }
     58 
     59 int height[Maxl];
     60 void get_he()
     61 {
     62     int k=0;
     63     for(int i=1;i<=cl;i++) if(rk[i]!=1)
     64     {
     65         int j=sa[rk[i]-1];
     66         if(k) k--;
     67         while(c[i+k]==c[j+k]&&i+k<=cl&&j+k<=cl) k++;
     68         height[rk[i]]=k;
     69     }
     70 }
     71 
     72 int d[Maxl][20];
     73 void rmq_init()
     74 {
     75     for(int i=1;i<=cl;i++) d[i][0]=height[i];
     76     for(int j=1;(1<<j)<=cl;j++)
     77       for(int i=1;i+(1<<j)-1<=cl;i++)
     78         d[i][j]=mymin(d[i][j-1],d[i+(1<<j-1)][j-1]);
     79 }
     80 
     81 int rmq(int x,int y)
     82 {
     83     int t;x=rk[x];y=rk[y];
     84     if(x>y) t=x,x=y,y=t;
     85     x++;
     86     int k=0;
     87     while((1<<k+1)<=y-x+1) k++;
     88     return mymin(d[x][k],d[y-(1<<k)+1][k]);
     89 }
     90 
     91 
     92 void ffind()
     93 {
     94     int ans=0;
     95     for(int i=1;i<=cl;i++)
     96     {
     97         for(int j=0;j<=cl/i;j++)
     98         {
     99             int now=j*i+1,x,y=0;
    100             if(c[now]!=c[now+l+i]||now+l+i>cl) continue;
    101             x=mymin(i,rmq(now,now+l+i));//向后匹配
    102             while(c[now-y-1]==c[now+l+i-y-1]&&y+1<i) y++;//向前匹配
    103             if(x+y-i+1>0) ans+=x+y-i+1;
    104         }
    105     }
    106     printf("%d
    ",ans);
    107 }
    108 
    109 int main()
    110 {
    111     int T,kase=0;
    112     scanf("%d",&T);
    113     while(T--)
    114     {
    115         init();
    116         get_sa(30);
    117         get_he();
    118         rmq_init();
    119         printf("Case %d: ",++kase);
    120         ffind();
    121     }
    122     return 0;
    123 }
    [UVA10829]

    2016-07-19 15:44:08


    这道题我看了100遍!!

    现在又明白了一点了ORZ。。。分块屌ORZ。。。

    好吧,是按照u的长度分块!!

    为什么呢,目的是:答案串的u至少包含一个分割点(上面的蓝色突起)

    我们对于其包含的第一个分割点时计算他!!!(就是上面红色圈起的部分)

    如果匹配长度越过第二个分割点,那么是会重复计算的,所以在这一题,向前匹配和向后匹配都可以直接while,越过分割点的时候就结束。

    ORZ。。。

    2016-11-13 14:52:25

  • 相关阅读:
    Gitlab安装之后不能正常启动案例解决
    SSH远程采用普通用户登录linux主机报错解决方法
    记一次AD域控客户端不能正常加域的故障处理
    Horizon7.9部署和克隆问题汇总
    VMware Guest customization fails on Linux
    Ubuntu18.04安装rabbitvcs svn图形化客户端和简单实用
    Ubuntu访问samba共享文件方法
    CentOS版本禁用Ctrl+Alt+Del重启功能
    02Kubernetes架构和组件
    01Kubernetes核心概念
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5685103.html
Copyright © 2011-2022 走看看