日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

[BZOJ 2555] SubString

發(fā)布時(shí)間:2025/4/16 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [BZOJ 2555] SubString 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Substring

題意

題面

給定一個(gè)初始字符串, 要求支持在這個(gè)字符串后添加字符串/查詢某個(gè)字符串作為子串的出現(xiàn)次數(shù).

強(qiáng)制在線.

長(zhǎng)度 \(\le600000\),詢問(wèn)次數(shù) \(\le10000\),詢問(wèn)總長(zhǎng)度 \(\le3000000\).

題解

看上去好像可以KMP增量構(gòu)造的樣子

實(shí)際上不行 (每次詢問(wèn)都得遍歷一遍原串)

考慮用另一個(gè)可以支持快速擴(kuò)展的維護(hù)字符串的算法: SAM.

但是SAM增量構(gòu)造的時(shí)候某個(gè)狀態(tài)對(duì)應(yīng)的 right 集合大小(也就是對(duì)應(yīng)子串的出現(xiàn)次數(shù))是 prt 樹(shù)上的子樹(shù)和的形式. 而且這個(gè)樹(shù)的形態(tài)會(huì)產(chǎn)生改變(又是煩人的nq結(jié)點(diǎn)搞的事情).

注意到這里求子樹(shù)和的時(shí)候不會(huì)換根, 于是我們可以在每次 link 的時(shí)候都把當(dāng)前點(diǎn)對(duì)所有祖先的貢獻(xiàn)都通過(guò)一次鏈上操作累加上去. 于是就可以比較容易地用LCT維護(hù)了.

然而寫(xiě)假了好幾次

一開(kāi)始寫(xiě)假是因?yàn)?Decode 出了鍋調(diào)了很久...因?yàn)槲乙恢币詾?mask 在 Decode 的時(shí)候也會(huì)變...

后來(lái)寫(xiě)假是因?yàn)?link/cut 的時(shí)候沒(méi)有把整個(gè)子樹(shù)的貢獻(xiàn)都累加上去 (這數(shù)據(jù)比較生草...這么大的錯(cuò)誤只掛了一個(gè)點(diǎn)...)

參考代碼

#include <bits/stdc++.h>const int MAXN=2e6+10; int size[MAXN];#define lch chd[0] #define rch chd[1] #define kch chd[k] #define xch chd[k^1]struct LinkCutTree{struct Node{int val;int add;bool rev;Node* prt;Node* pprt;Node* chd[2];Node(int x):val(x),add(0),rev(false),prt(NULL),pprt(NULL){this->lch=this->rch=NULL;}void Flip(){if(this!=NULL){this->rev=!this->rev;std::swap(this->lch,this->rch);}}void Add(int x){if(this!=NULL){this->val+=x;this->add+=x;}}void PushDown(){if(this->add!=0){this->lch->Add(this->add);this->rch->Add(this->add);this->add=0;}if(this->rev){this->lch->Flip();this->rch->Flip();this->rev=false;}}};std::vector<Node*> N;LinkCutTree():N(1){}void Rotate(Node* root,int k){Node* tmp=root->xch;root->PushDown();tmp->PushDown();tmp->prt=root->prt;if(root->prt==NULL){tmp->pprt=root->pprt;root->pprt=NULL;}else if(root->prt->lch==root)root->prt->lch=tmp;elseroot->prt->rch=tmp;root->xch=tmp->kch;if(root->xch!=NULL)root->xch->prt=root;tmp->kch=root;root->prt=tmp;}void Splay(Node* root){while(root->prt!=NULL){int k=root->prt->lch==root;if(root->prt->prt==NULL)Rotate(root->prt,k);else{int d=root->prt->prt->lch==root->prt;Rotate(k==d?root->prt->prt:root->prt,k);Rotate(root->prt,d);}}}void Expose(Node* root){Splay(root);root->PushDown();if(root->rch!=NULL){root->rch->prt=NULL;root->rch->pprt=root;root->rch=NULL;}}bool Splice(Node* root){Splay(root);if(root->pprt==NULL)return false;Expose(root->pprt);root->pprt->rch=root;root->prt=root->pprt;root->pprt=NULL;return true;}void Access(Node* root){Expose(root);while(Splice(root));assert(root->pprt==0&&root->prt==0);}void Evert(Node* root){Access(root);root->Flip();}void Add(int y,int d){Evert(N[1]);Access(N[y]);N[y]->Add(d);}void Link(int prt,int son){Evert(N[son]);N[son]->pprt=N[prt];Evert(N[1]);Access(N[prt]);N[prt]->Add(N[son]->val);}void Cut(int prt,int son){Evert(N[1]);Access(N[son]);Access(N[prt]);N[prt]->Add(-N[son]->val);Access(N[son]);N[son]->PushDown();N[son]->lch->prt=NULL;N[son]->lch=NULL;}int Query(int x){Access(N[x]);return N[x]->val;}void MakeTree(int x){N.push_back(new Node(x));} }*T=new LinkCutTree();int q; int cnt=1; int root=1; int last=1; char s[MAXN]; int prt[MAXN]; int len[MAXN]; std::map<char,int> chd[MAXN];int Query(char*); void Extend(char); void Extend(char*); void Decode(char*,int);int main(){scanf("%d",&q);scanf("%s",s);T->MakeTree(0);Extend(s);int mask=0;while(q--){scanf("%s",s);if(*s=='A'){scanf("%s",s);Decode(s,mask);Extend(s);}else{scanf("%s",s);Decode(s,mask);int x=Query(s);mask^=x;printf("%d\n",x);}}return 0; }int Query(char* s){int cur=root;while(*s!='\0'){if(!chd[cur].count(*s))return 0;elsecur=chd[cur][*s];++s;}return T->Query(cur); }void Decode(char* s,int mask){int len=strlen(s);for(int i=0;i<len;i++){mask=(mask*131+i)%len;char t=s[i];s[i]=s[mask];s[mask]=t;} }void Extend(char* s){while(*s!='\0')Extend(*(s++)); }void Extend(char x){int p=last;int np=++cnt;T->MakeTree(1);size[last=np]=1;len[np]=len[p]+1;while(p&&!chd[p].count(x))chd[p][x]=np,p=prt[p];if(p==0)prt[np]=root;else{int q=chd[p][x];if(len[q]==len[p]+1)prt[np]=q;else{int nq=++cnt;T->MakeTree(0);chd[nq]=chd[q];prt[nq]=prt[q];T->Cut(prt[q],q);T->Link(prt[nq],nq);prt[q]=nq;T->Link(nq,q);prt[np]=nq;len[nq]=len[p]+1;while(p&&chd[p][x]==q)chd[p][x]=nq,p=prt[p];}}T->Link(prt[np],np); }

轉(zhuǎn)載于:https://www.cnblogs.com/rvalue/p/10359563.html

總結(jié)

以上是生活随笔為你收集整理的[BZOJ 2555] SubString的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。