zoukankan      html  css  js  c++  java
  • CF1056E Check Transcription(SA)

    对于本题,要发现的一点是,因为0,1各代表一个字符串,因此我们可以暴力枚举0代表的是什么,1代表的是什么,一个是前缀,另一个受前一个控制。

    对于判断两个子串是否相等,可以使用哈希,这里我采用的是后缀数组求lcp,只要比较一下是否大于等于我们枚举的长度即可。

    最后我们要判断一下0和1代表的东西不能够相等

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    typedef pair<int,pll> plll;
    const int N=1e6+10;
    const int mod=1e9+7;
    char s[N],t[N];
    int sa[N],rk[N],od[N],cnt[N],id[N],px[N];
    ll h[N];
    ll f[N][26];
    ll lg[N];
    bool cmp(int x, int y, int w) {
      return od[x]==od[y]&&od[x + w]==od[y + w];
    }
    void da(int n,int m){
        int i;
        memset(cnt,0,sizeof cnt);
        for(i=1;i<=n;i++) cnt[rk[i]=t[i]]++;
        for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
        for(i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
        int p;
        for(int w=1;w<n;w<<=1,m=p){
            p=0;
            for(i=n;i>n-w;i--)
                id[++p]=i;
            for(i=1;i<=n;i++)
                if(sa[i]>w)
                    id[++p]=sa[i]-w;
            memset(cnt,0,sizeof cnt);
            for(i=1;i<=n;i++) cnt[px[i]=rk[id[i]]]++;
            for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
            for(i=n;i>=1;i--) sa[cnt[px[i]]--]=id[i];
            for(i=0;i<=n;i++) od[i]=rk[i];
            for(p=0,i=1;i<=n;i++){
                rk[sa[i]]=cmp(sa[i-1],sa[i],w)?p:++p;
            }
        }
    }
    void st(int n){
        int i,j;
        for(i=1;i<=n;i++)
            f[i][0]=h[i];
        lg[1]=0;
        for(i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(j=1;j<=lg[n];j++){
            for(i=1;i+(1<<j)-1<=n;i++){
                f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
            }
        }
    }
    int query(int l,int r){
        if(l>r)
            swap(l,r);
        l++;
        int len=lg[r-l+1];
        return min(f[l][len],f[r-(1<<len)+1][len]);
    }
    void get_height(int n){
        int i;
        for(i=1;i<=n;i++){
            if(rk[i]==1)
                continue;
            int a=max(h[rk[i-1]]-1,1ll*0);
            while(i+a<=n&&t[i+a]==t[sa[rk[i]-1]+a])
                a++;
            h[rk[i]]=a;
        }
        st(n);
    }
    int main(){
        //ios::sync_with_stdio(false);
        scanf("%s%s",s+1,t+1);
        int lent=strlen(t+1);
        int lens=strlen(s+1);
        da(lent,128);
        get_height(lent);
        int cnt0=0,cnt1=0;
        for(int i=1;i<=lens;i++){
            if(s[i]=='0')
                cnt0++;
            else
                cnt1++;
        }
        ll ans=0;
        for(ll i=1;i*cnt0<=lent;++i){
            if((lent-i*cnt0)%(lens-cnt0))continue;
            ll start0=0,start1=0,pos=1,flag=1;
            ll k=(lent-i*cnt0)/(lens-cnt0);
            for(ll j=1;j<=lens;++j){
                if(s[j]=='0'){
                    if(!start0)start0=pos;
                    else if(query(rk[start0],rk[pos])<i)flag=0;
                    pos+=i;
                }
                else{
                    if(!start1)start1=pos;
                    else if(query(rk[start1],rk[pos])<k)flag=0;
                    if(!k)flag=0;
                    pos+=k;
                }
            }
            if(flag&&(i!=k||query(rk[start0],rk[start1])<i))++ans;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    git 常用命令总结
    Activiti(工作流)如何关联业务表
    常见数据结构复杂度
    linux 启动 oracle数据库
    word2vec 入门(三)模型介绍
    数组中出现次数超过一半的数字 -java
    word2vec 入门(二)使用教程篇
    word2vec 入门基础(一)
    Stackoverflow上人气最旺的10个Java问题(转ImportNew)
    leetcode 326. Power of Three(不用循环或递归)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13555323.html
Copyright © 2011-2022 走看看