不懂就问
  • 板块学术版
  • 楼主JK_LOVER
  • 当前回复4
  • 已保存回复4
  • 发布时间2020/9/24 22:05
  • 上次更新2023/11/5 12:40:17
查看原帖
不懂就问
227824
JK_LOVER楼主2020/9/24 22:05

什么时候,线段树合并必须新开节点?为什么?如下CF1037H Security 代码,只有新开才是对的,可能问题比较蠢,但还是希望大佬们指教。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 100;
struct Node{int len,link,nxt[26];}st[N<<1];
int last = 0,si = 0;
int lc[N * 20],rc[N * 20],rt[N],cnt[N * 20],size,n,m;
vector<int> G[N];

void insert(int &u,int l,int r,int pos) {
    u = ++size;cnt[u]++;if(l == r) return;
    int mid = l + r >> 1;
    // cout << u << endl;
    if(pos <= mid) insert(lc[u],l,mid,pos);
    else insert(rc[u],mid+1,r,pos);
}
int merge(int x,int y,int l,int r) {
    // cout << x << " " << y << endl;
    if(!x || !y) return x|y;
    int mid = l + r >> 1;
    cnt[x] = cnt[x] + cnt[y];
    if(l == r) return x;
    lc[x] = merge(lc[x],lc[y],l,mid);
    rc[x] = merge(rc[x],rc[y],mid+1,r);
    return x;
}
int merge(int x,int y,int l,int r) {
    // cout << x << " " << y << endl;
    if(!x || !y) return x|y;
    int mid = l + r >> 1;int i = ++size;
    cnt[i] = cnt[x] + cnt[y];
    if(l == r) return i;
    lc[i] = merge(lc[x],lc[y],l,mid);
    rc[i] = merge(rc[x],rc[y],mid+1,r);
    return i;
}
bool ask(int u,int l,int r,int L,int R) {
    if(!u) return 0;
    if(l > R || r < L) return 0;
    if(L <= l && r <= R) return (cnt[u] > 0);
    int mid = l + r >> 1;
    return ((ask(lc[u],l,mid,L,R) + (ask(rc[u],mid+1,r,L,R))) > 0);
}
void init() {st[0].link = -1;si++;}
void insert(int c,int endpos) {
    int cur = si++;st[cur].len = st[last].len + 1;
    int p = last; insert(rt[cur],1,n,endpos);
    while(p != -1 && !st[p].nxt[c]) {
        st[p].nxt[c] = cur;p = st[p].link;
    }
    if(p == -1) st[cur].link = 0;
    else {
        int q = st[p].nxt[c];
        if(st[q].len == st[p].len + 1) st[cur].link = q;
        else {
            int cl = si++;st[cl].len = st[p].len + 1;st[cl].link = st[q].link;
            for(int i = 0;i < 26;i++) st[cl].nxt[i] = st[q].nxt[i];
            while(p != -1 && st[p].nxt[c] == q) {
                st[p].nxt[c] = cl;p = st[p].link;
            }
            st[cur].link = st[q].link = cl;
        }
    }
    // cout << (char)('a' + c) << endl;
    last = cur;
}
char S[N],ch[N];
int stk[N],top;
void dfs(int x) {for(auto y:G[x]) {dfs(y);rt[x] = merge(rt[x],rt[y],1,n);}}
int main() {
    scanf("%s%d",S+1,&m);n = strlen(S+1);init();
    for(int i = 1;i <= n;i++) insert(S[i]-'a',i);
    for(int i = 1;i < si;i++) {G[st[i].link].push_back(i);/*cout << st[i].link <<" " << i << endl;*/};
    // cout << "debug1" << endl;
    dfs(0);rt[0] = 0;
    // cout << "debug2" << endl;
    while(m--) {
        // cout << "debug3 " << m << endl;
        int l,r;scanf("%d%d%s",&l,&r,ch+1);int len = strlen(ch+1);
        // cout << "debug4 " << ch+1 << endl;
        // cout << len << endl;
        stk[top = 1] = 0;ch[len + 1] = 'a' - 1;
        for(int i = 1,p = 0;i <= len && st[p].nxt[ch[i] - 'a'];i++) 
        stk[++top] = p = st[p].nxt[ch[i] - 'a'];
        bool check = 0;
        // cout <<"look "<< r-l+1 <<" " << top << endl;
        for(int i = min(r-l+1,top);i >= 1 && (check==0);i--) {
            for(int j = ch[i] - 'a' + 1;j < 26;j++) {
                // if(st[stk[top]].nxt[j]== 0) continue; 
                if(ask(rt[ st[stk[i]].nxt[j] ],1,n,l+i-1,r)) {
                    // cout << "debug5 " <<i << endl;
                    for(int k = 1;k < i;k++) printf("%c",ch[k]);
                     // cout << j << endl;
                    printf("%c",(char)(j + 'a'));
                    printf("\n");
                    check = 1;
                    // cout << "debug6 " << endl;
                    break;
                }
            }
        }
        if(check == 0) puts("-1");
    }
}

2020/9/24 22:05
加载中...