WA on#2 求问思路是否假
查看原帖
WA on#2 求问思路是否假
544310
wuhupai楼主2025/1/23 09:00

小样例拍了10min,没有错误

前面的帖子看过了

将s和t都插入广义SAM,然后线段树合并parent树里的t的颜色数和出现次数。然后查询找到广义SAM上s的子串所在的状态,然后在这里查线段树

#include<bits/stdc++.h>
#define for1(i,a,b) for( int i=(a);i<=(b);i++)
#define for2(i,a,b) for( int i=(a);i<(b);i++)
#define for3(i,a,b) for( int i=(a);i>=(b);i--)
#define for4(i,a,b) for( int i=(a);i>(b);i--)
#define puba push_back
#define mem(a,b) memset((a),(b),sizeof((a)))
using namespace std;
int n,cnt,b[1100005],c[500005],T,l,r,x,y;
int son[1100005][26];
string s,t[50005];
void insert(string s){
    int n=s.size(),u=1;
    for2(i,0,n){
        int c=s[i]-'a';
        if(!son[u][c]) son[u][c]=++cnt;
        u=son[u][c];
    }
}
struct node{
    int maxx,id;
}d[1100005*25];
struct segment{
    int ll[1100005*25],rr[1100005*25],cnt;
    node merge(node x,node y){
        if(x.maxx<y.maxx) return y;
        return x;
    }
    void push_up(int p){
        d[p]=merge(d[ll[p]],d[rr[p]]);
    }
    void update(int l,int r,int &p,int s){
        if(!p) p=++cnt;
        if(l==r){
            d[p].maxx=1;
            d[p].id=l;
            // cout<<l<<"-"<<p<<"\n";
            return;
        }
        int mid=(l+r)>>1;
        if(s<=mid) update(l,mid,ll[p],s);
        else update(mid+1,r,rr[p],s);
        push_up(p);
    }
    void merge(int l,int r,int p1,int p2){
        if(l==r){
            d[p1].maxx+=d[p2].maxx;
            d[p1].id=l;
            return;
        }
        int mid=(l+r)>>1;
        if(ll[p1]&&ll[p2]) merge(l,mid,ll[p1],ll[p2]);
        else if(ll[p2]) ll[p1]=ll[p2];
        if(rr[p1]&&rr[p2]) merge(mid+1,r,rr[p1],rr[p2]);
        else if(rr[p2]) rr[p1]=rr[p2];
        push_up(p1);
    }
    node getsum(int l,int r,int p,int s,int t){
        if(!p) return {0,0};
        if(l>=s&&r<=t) return d[p];
        int mid=(l+r)>>1;
        node ans={0,0};
        if(s<=mid) ans=merge(ans,getsum(l,mid,ll[p],s,t));
        if(t>mid) ans=merge(ans,getsum(mid+1,r,rr[p],s,t));
        return ans;
    }
    void print(int l,int r,int p){
        if(!p) return;
        if(l==r){
            cout<<l<<"-"<<d[p].maxx<<" "<<p<<"\n";
            return;
        }
        int mid=(l+r)>>1;
        print(l,mid,ll[p]);
        print(mid+1,r,rr[p]);
    }
}seg;
struct gsam{
    int cnt,pos[1100005],h[1100005][22],pos1[500005];
    struct node{
        int nxt[26],link,len;
    }st[1100005];
    void insert(int c,int &lst){
        int cur=++cnt,p=lst;
        st[cur].len=st[lst].len+1;
        lst=cur;
        while(p&&!st[p].nxt[c]){
            st[p].nxt[c]=cur;
            p=st[p].link;
        }
        if(!p){
            st[cur].link=1;
            return;
        }
        int q=st[p].nxt[c];
        if(st[p].len+1==st[q].len){
            st[cur].link=q;
            return;
        }
        int clone=++cnt;
        st[clone]=st[q];
        st[clone].len=st[p].len+1;
        st[cur].link=st[q].link=clone;
        while(p&&st[p].nxt[c]==q){
            st[p].nxt[c]=clone;
            p=st[p].link;
        }
    }
    void bfs(){
        queue<int>q;
        q.push(1);
        pos[1]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for2(i,0,26){
                int to=son[u][i];
                if(!to) continue;
                pos[to]=pos[u];
                insert(i,pos[to]);
                q.push(to);
            }
        }
    }
    void build(){
        for1(i,1,cnt) h[i][0]=st[i].link;
        for1(j,1,21)
            for1(i,1,cnt)
                h[i][j]=h[h[i][j-1]][j-1];
        for1(i,1,cnt) c[st[i].len]++;
        for1(i,1,5e5) c[i]+=c[i-1];
        for1(i,1,cnt) b[c[st[i].len]--]=i;
        for3(i,cnt,2){
            int u=st[b[i]].link,to=b[i];
            // cout<<u<<" "<<to<<"\n";
            // cout<<n<<"\n";
            seg.merge(1,n,u,to);
        }
    }
    void upd(string s,int id){
        int len=s.size(),u=1;
        for2(i,0,len){
            u=son[u][s[i]-'a'];
            // cout<<pos[u]<<":"<<id<<"\n";
            seg.update(1,n,pos[u],id);
            // seg.print(1,n,pos[u]);
        }
        // for1(i,1,cnt){
        //     // cout<<id<<"\n";
        //     // cout<<1<<"\n";
        //     seg.print(1,3,i);
        // }
    }
    void pre(){
        int u=1,n=s.size();
        for2(i,0,n){
            u=son[u][s[i]-'a'];
            pos1[i]=pos[u];
        }
    }
    int get(int l,int r){
        int u=pos1[r-1];
        for3(i,21,0)
            if(st[h[u][i]].len>=(r-l+1)) u=h[u][i];
        return u;
    }
}sam;
signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    // freopen("make.in","r",stdin);
    // freopen("my.out","w",stdout);
    sam.cnt=cnt=1;
    cin>>s;
    insert(s);
    cin>>n;
    for1(i,1,n) cin>>t[i],insert(t[i]);
    sam.bfs();
    seg.cnt=sam.cnt;
    sam.pre();
    for1(i,1,n){
        sam.upd(t[i],i);
    }
    sam.build();
    // seg.print(1,3,11);
    cin>>T;
    while(T--){
        cin>>l>>r>>x>>y;
        int u=sam.get(x,y);
        // cout<<u<<"\n";
        node ans=seg.getsum(1,n,u,l,r);
        if(ans.maxx==0) cout<<l<<" "<<0<<"\n";
        else cout<<ans.id<<" "<<ans.maxx<<"\n";
    }
    // cout<<1;
    
    return 0;
}
2025/1/23 09:00
加载中...