zoukankan      html  css  js  c++  java
  • L-Gap Substrings(uva 10829)

    题意:有一种形如uvu形式的字符串,其中u是非空字符串,且V的长度正好为L,那么称这个字符串为L-Gap字符串
    给出一个字符串S,以及一个正整数L,问S中有多少个L-Gap子串. 

    /*
        这道题用到一个常用的技巧(虽然我这是第一次见)。
        枚举U的长度,然后每隔U枚举i,然后确定j,则j一定在另一个U里面,有了i、j之后,向左向右扩展,看看能匹配多长。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 600010
    using namespace std;
    int t1[N],t2[N],c[N],s[N],sa[N],rk[N],height[N],n;
    int st[N][21],lg2[N];
    char ch[N];
    bool cmp(int *y,int a,int b,int k){
        int a1=y[a],b1=y[b];
        int a2=a+k<=n?y[a+k]:-1;
        int b2=b+k<=n?y[b+k]:-1;
        return a1==b1&&a2==b2;
    }
    void DA(){
        int *x=t1,*y=t2,m=27;
        for(int i=1;i<=m;i++) c[i]=0;
        for(int i=1;i<=n;i++) c[x[i]=s[i]]++;
        for(int i=2;i<=m;i++) c[i]+=c[i-1];
        for(int i=n;i;i--) sa[c[x[i]]--]=i;
        for(int k=1,p=0;k<=n;k*=2,m=p,p=0){
            for(int i=n-k+1;i<=n;i++) y[++p]=i;
            for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
            for(int i=1;i<=m;i++) c[i]=0;
            for(int i=1;i<=n;i++) c[x[y[i]]]++;
            for(int i=2;i<=m;i++) c[i]+=c[i-1];
            for(int i=n;i;i--) sa[c[x[y[i]]]--]=y[i];
            swap(x,y);p=1;x[sa[1]]=1;
            for(int i=2;i<=n;i++)
                if(cmp(y,sa[i-1],sa[i],k)) x[sa[i]]=p;
                else x[sa[i]]=++p;
            if(p>=n) break;
        }
    }
    void geth(){
        for(int i=1;i<=n;i++) rk[sa[i]]=i;
        for(int i=1,j=0;i<=n;i++){
            while(s[i+j]==s[sa[rk[i]-1]+j]) j++;
            height[rk[i]]=j;
            if(j) j--;
        }
        for(int i=2;i<=n;i++) lg2[i]=lg2[i>>1]+1;
        for(int i=1;i<=n;i++) st[i][0]=height[i];
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i+(1<<j)-1<=n;i++)
                st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
    }
    int query(int l,int r){
        l=rk[l];r=rk[r];
        if(l>r) swap(l,r);
        int k=lg2[r-l];
        return min(st[l+1][k],st[r-(1<<k)+1][k]);
    }
    int main(){
        int T;scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            long long ans=0;int G;
            scanf("%d%s",&G,ch+1);
            int len=strlen(ch+1);
            for(int i=1;i<=len;i++) s[i]=s[len*2-i+2]=ch[i]-'a'+1;
            s[len+1]=27;n=len*2+1;
            DA();geth();
            for(int U=1;U*2+G<=len;U++)
                for(int i=1;i+U+G<=len;i+=U){
                    int j=i+U+G;
                    if(s[i]!=s[j]) continue;
                    int L=min(U,query(i,j))+min(U,query(len*2-i+2,len*2-j+2))-1;//分别为向右和向左扩展 
                    if(L>=U) ans+=L-U+1;
                }
            cout<<"Case "<<cas<<": "<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    JDK1.8源码(四)——java.util.Arrays类
    JDK1.8源码(三)——java.lang.String类
    Java基础(六)——集合
    设计模式(二)——单例模式
    当你忘了数据库的设计语句,看这一篇就能拾起记忆
    MyBatis之配置优化
    Mybatis中的一些配置,直接拿来就可以用
    网络编程---ip&端口
    java基础数据类型小知识
    学习了MarkDown文本工具
  • 原文地址:https://www.cnblogs.com/harden/p/6597077.html
Copyright © 2011-2022 走看看