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
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/13555323.html