什么时候,线段树合并必须新开节点?为什么?如下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");
}
}