题解:AT_abc403_e [ABC403E] Forbidden Prefix

· · 题解

省流:学 DS 学傻了。

题意

m 次操作。\ 每次往集合 A 或集合 B 中加入一个字符串 S。\ 每次插入完后查询 B 中没有 A 中元素作为前缀的字符串数。

## solution 看到前缀匹配,不难想到字典树。\ 先离线下来建出字典树。\ 如果插入到集合 $B$ 中,就是树上单点加。\ 如果插入到集合 $A$ 中,就是给子树标号,也就是这一子树以后的值一直都只能为 $0$。\ 直接把字典树拍到 DFS 序上维护子树信息即可。 ## code ```cpp #include<bits/stdc++.h> using namespace std; namespace fast_IO {//我向众神祈祷,回应我的只有心跳 #define IOsiz 100000 char ibuf[IOsiz], obuf[IOsiz], *p1 = ibuf, *p2 = ibuf, *p3 = obuf; #define getchar() ((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOsiz,stdin),p1==p2)?(EOF):(*p1++)) #define putchar(x) ((p3==obuf+IOsiz)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x) #define isdigit(ch) (ch>47&&ch<58) #define isspace(ch) (ch<33) template<typename T> inline T read() { T s = 0; int w = 1; char ch; while (ch = getchar(), !isdigit(ch) and (ch != EOF)) if (ch == '-') w = -1; if (ch == EOF) return false; while (isdigit(ch)) s = s * 10 + ch - 48, ch = getchar(); return s * w; } template<typename T> inline bool read(T &s) { s = 0; int w = 1; char ch; while (ch = getchar(), !isdigit(ch) and (ch != EOF)) if (ch == '-') w = -1; if (ch == EOF) return false; while (isdigit(ch)) s = s * 10 + ch - 48, ch = getchar(); return s *= w, true; } template<typename T> inline void print(T x) { if (x < 0) putchar('-'), x = -x; if (x > 9) print(x / 10); putchar(x % 10 + 48); } inline bool read(char &s) { while (s = getchar(), isspace(s)); return true; } inline bool read(char *s) { char ch; while (ch = getchar(), isspace(ch)); if (ch == EOF) return false; while (!isspace(ch)) *s++ = ch, ch = getchar(); *s = '\000'; return true; } inline void print(char x) { putchar(x); } inline void print(char *x) { while (*x) putchar(*x++); } inline void print(const char *x) { for (int i = 0; x[i]; i++) putchar(x[i]); } inline bool read(std::string& s) { s = ""; char ch; while (ch = getchar(), isspace(ch)); if (ch == EOF) return false; while (!isspace(ch)) s += ch, ch = getchar(); return true; } inline void print(std::string x) { for (int i = 0, n = x.size(); i < n; i++) putchar(x[i]); } inline bool read(bool &b) { char ch; while(ch=getchar(), isspace(ch)); b=ch^48; return true; } inline void print(bool b) { putchar(b+48); } template<typename T, typename... T1> inline int read(T& a, T1&... other) { return read(a) + read(other...); } template<typename T, typename... T1> inline void print(T a, T1... other) { print(a), print(other...); } struct Fast_IO { ~Fast_IO() { fwrite(obuf, p3 - obuf, 1, stdout); } } io; template<typename T> Fast_IO& operator >> (Fast_IO &io, T &b) { return read(b), io; } template<typename T> Fast_IO& operator << (Fast_IO &io, T b) { return print(b), io; } #define cout io #define cin io #define endl '\n' } using namespace fast_IO; #define int long long const int maxn=1e6; struct node{ int ch[26]; }trie[maxn+5]; int q,pos[maxn+5]; int op[maxn+5],rt,tot,dfn[maxn+5],siz[maxn+5],idx; string s[maxn+5]; void insert(string &s,int id){ int now=1; for(int i=0;i<s.size();i++){ int c=s[i]-'a'; int &v=trie[now].ch[c]; if(!v)v=++tot; now=v; } pos[id]=now; } void dfs(int now){ siz[now]=1; dfn[now]=++idx; for(int i=0;i<26;i++){ int to=trie[now].ch[i]; if(!to)continue; dfs(to); siz[now]+=siz[to]; } } struct segmenttree{ struct node{ int lef,rig,tag,sum; }tree[maxn<<2|1]; void pushup(int now){ tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; if(tree[now].tag)tree[now].sum=0; } void build(int now,int lef,int rig){ tree[now].lef=lef,tree[now].rig=rig; if(lef==rig)return; int mid=lef+rig>>1; build(now<<1,lef,mid); build(now<<1|1,mid+1,rig); pushup(now); } void modify(int now,int lef,int rig){ if(lef<=tree[now].lef&&tree[now].rig<=rig)return tree[now].tag=1,tree[now].sum=0,void(); int mid=tree[now].lef+tree[now].rig>>1; if(lef<=mid)modify(now<<1,lef,rig); if(mid<rig)modify(now<<1|1,lef,rig); pushup(now); } void update(int now,int to){//注意可能有重复的串 if(tree[now].tag)return; if(tree[now].lef==tree[now].rig)return tree[now].sum=(tree[now].tag?0:tree[now].sum+1),void(); int mid=tree[now].lef+tree[now].rig>>1; if(to<=mid)update(now<<1,to); else update(now<<1|1,to); pushup(now); } }tr; signed main(){ rt=tot=1; cin>>q; for(int i=1;i<=q;i++)cin>>op[i]>>s[i],insert(s[i],i); dfs(rt); tr.build(1,1,idx); for(int i=1;i<=q;i++){ int x=pos[i]; if(op[i]==1){ tr.modify(1,dfn[x],dfn[x]+siz[x]-1); }else{ tr.update(1,dfn[x]); } cout<<tr.tree[1].sum<<"\n"; } return 0; } ```