题解:SP3109 STRLCP - Longest Common Prefix
三倍经验:
题意
维护一个字符串
-
:输出 -
:用 替换 的第 个字符 -
: 在 的第 个字符后插入
分析
看到 LCP 相关的操作,想到后缀全家桶。
但是发现并不是很好操作。
考虑使用万能的哈希。
我们可以二分长度
因为有插入操作,所以使用平衡树维护哈希。
单次查询时间复杂度
Code
#include<bits/stdc++.h> using namespace std; #define lx 323 typedef uint64_t hash_t; #define maxn 400005 hash_t lev[maxn]; struct Treap { #define siz(x) (x?x->siz:0) #define hsh(x) (x?x->hsh:0) #define rhsh(x) (x?x->rhsh:0) mt19937 rnd; Treap(uint32_t s=114) { rnd.seed(s); } struct node { node *lc, *rc; uint32_t siz, id; uint8_t ch; hash_t hsh, rhsh; node(uint8_t c, uint32_t i) { id=i; lc=rc=nullptr; siz=1, hsh=rhsh=ch=c; } node *push_up() { siz=siz(lc)+siz(rc)+1; hsh=lev[siz(rc)+1]*hsh(lc)+lev[siz(rc)]*ch+hsh(rc); rhsh=lev[siz(lc)+1]*rhsh(rc)+lev[siz(lc)]*ch+rhsh(lc); return this; } }; node *rt; node *new_node(uint8_t c) { return new node(c, rnd()); } void split(node *x, uint32_t k, node *&l, node *&r) { if(!x) return l=r=0, void(); if(siz(x->lc)<k) l=x, split(x->rc, k-siz(x->lc)-1, x->rc, r); else r=x, split(x->lc, k, l, x->lc); x->push_up(); } node *merge(node *x, node *y) { if(!x||!y) return x?x:y; if(x->id<y->id) { x->rc=merge(x->rc, y); return x->push_up(); } else { y->lc=merge(x, y->lc); return y->push_up(); } } void push_back(uint8_t c) { rt=merge(rt, new_node(c)); } void insert(int p, uint8_t c) { node *a, *b; split(rt, p, a, b); rt=merge(a, merge(new_node(c), b)); } void modify(int p, uint8_t ch) { node *a, *b, *c; split(rt, p-1, a, b); split(b, 1, b, c); b->hsh=b->rhsh=b->ch=ch; rt=merge(merge(a, b), c); } hash_t query(int l, int r) { node *a, *b, *c; split(rt, l-1, a, b); split(b, r-l+1, b, c); hash_t ret=b->hsh; rt=merge(merge(a, b), c); return ret; } }tr(114514); string s; bool chk(int p1, int p2, int l, int mxlen) { if(p1+l-1>mxlen||p2+l-1>mxlen) return 0; hash_t h1=tr.query(p1, p1+l-1); hash_t h2=tr.query(p2, p2+l-1); return h1==h2; } int LCP(int p1, int p2) { if(!tr.rt) return 0; int len=tr.rt->siz; int ret=0; for(int i=1<<20;i;i>>=1) if(chk(p1, p2, ret+i, len)) ret+=i; return ret; } void solve() { tr.rt=0; int m; cin>>s; for(auto c:s) tr.push_back(c); cin>>m; while(m--) { char op, c; int p, x; cin>>op>>p; if(op=='I') cin>>c, tr.insert(p, c); if(op=='R') cin>>c, tr.modify(p, c); if(op=='Q') cin>>x, cout<<LCP(p, x)<<'\n'; } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); lev[0]=1; for(int i=1;i<maxn;i++) lev[i]=lev[i-1]*lx; int t; cin>>t; while(t--) solve(); }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18379538
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步