zoukankan      html  css  js  c++  java
  • BZOJ4892 Tjoi2017dna(后缀数组)

      对每个子串暴力匹配至失配三次即可。可以用SA查lcp。然而在bzoj上被卡常了。当然也可以二分+哈希或者SAM甚至FFT。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int T,n,m,sa[N],sa2[N],rk[N<<1],tmp[N<<1],lg2[N],cnt[N],h[N],f[N][19];
    char s[N],s2[N];
    void make(int n)
    {
        memset(cnt,0,sizeof(cnt));
        int m=0;
        for (int i=1;i<=n;i++) cnt[rk[i]=s[i]]++,m=max(m,(int)s[i]);
        for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
        for (int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
        for (int k=1;k<=n;k<<=1)
        {
            int p=0;
            for (int i=n-k+1;i<=n;i++) sa2[++p]=i;
            for (int i=1;i<=n;i++) if (sa[i]>k) sa2[++p]=sa[i]-k;
            memset(cnt,0,m+1<<2);
            for (int i=1;i<=n;i++) cnt[rk[i]]++;
            for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
            for (int i=n;i>=1;i--) sa[cnt[rk[sa2[i]]]--]=sa2[i];
            memcpy(tmp,rk,sizeof(rk));
            p=1;rk[sa[1]]=1;
            for (int i=2;i<=n;i++)
            {
                if (tmp[sa[i]]!=tmp[sa[i-1]]||tmp[sa[i]+k]!=tmp[sa[i-1]+k]) p++;
                rk[sa[i]]=p;
            }
            if (p==n) break;
            m=p;
        }
        for (int i=1;i<=n;i++)
        {
            h[i]=max(h[i-1]-1,0);
            while (s[i+h[i]]==s[sa[rk[i]-1]+h[i]]) h[i]++;
        }
        for (int i=1;i<=n;i++) f[i][0]=h[sa[i]];
        for (int j=1;j<19;j++)
            for (int i=1;i<=n;i++)
            f[i][j]=min(f[i][j-1],f[min(i+(1<<j-1),n)][j-1]);
        lg2[1]=0;
        for (int i=2;i<=n;i++)
        {
            lg2[i]=lg2[i-1];
            if ((2<<lg2[i])<=i) lg2[i]++;
        }
    }
    int query(int x,int y)
    {
        x=rk[x],y=rk[y];
        if (x==y) return N;
        if (x>y) swap(x,y);x++;
        return min(f[x][lg2[y-x+1]],f[y-(1<<lg2[y-x+1])+1][lg2[y-x+1]]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4892.in","r",stdin);
        freopen("bzoj4892.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        T=read();
        while (T--)
        {
            scanf("%s",s+1);n=strlen(s+1);
            scanf("%s",s2+1);m=strlen(s2+1);
            for (int i=1;i<=m;i++) s[n+i]=s2[i];
            make(n+m);
            int ans=0;
            for (int i=1;i<=n-m+1;i++)
            {
                int x=i;
                for (int j=1;j<=3&&x-i+1<=m;j++)
                {
                    x+=query(x,n+x-i+1);
                    x++;
                }
                if (x-i+1<=m) x+=query(x,n+x-i+1);
                if (x-i+1>m) ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    hdu 5646 DZY Loves Partition
    bzoj 1001 狼抓兔子 平面图最小割
    poj 1815 Friendship 最小割 拆点 输出字典序
    spoj 1693 Coconuts 最小割 二者取其一式
    hdu 5643 King's Game 约瑟夫环变形
    约瑟夫环问题
    hdu 5642 King's Order
    CodeForces 631C Report
    1039: C语言程序设计教程(第三版)课后习题9.4
    1043: C语言程序设计教程(第三版)课后习题10.1
  • 原文地址:https://www.cnblogs.com/Gloid/p/10034062.html
Copyright © 2011-2022 走看看