日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

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

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)

發(fā)布時(shí)間:2024/4/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Description

打字機(jī)上只有28個(gè)按鍵,分別印有26個(gè)小寫(xiě)英文字母和'B'、'P'兩個(gè)字母。經(jīng)阿貍研究發(fā)現(xiàn),這個(gè)打字機(jī)是這樣工作的:

·輸入小寫(xiě)字母,打字機(jī)的一個(gè)凹槽中會(huì)加入這個(gè)字母(這個(gè)字母加在凹槽的最后)。

·按一下印有'B'的按鍵,打字機(jī)凹槽中最后一個(gè)字母會(huì)消失。

·按一下印有'P'的按鍵,打字機(jī)會(huì)在紙上打印出凹槽中現(xiàn)有的所有字母并換行,但凹槽中的字母不會(huì)消失。

例如,阿貍輸入aPaPBbP,紙上被打印的字符如下:

a aa ab 我們把紙上打印出來(lái)的字符串從1開(kāi)始順序編號(hào),一直到n。打字機(jī)有一個(gè)非常有趣的功能,在打字機(jī)中暗藏一個(gè)帶數(shù)字的小鍵盤(pán),在小鍵盤(pán)上輸入兩個(gè)數(shù)(x,y)(其中1≤x,y≤n),打字機(jī)會(huì)顯示第x個(gè)打印的字符串在第y個(gè)打印的字符串中出現(xiàn)了多少次。

阿貍發(fā)現(xiàn)了這個(gè)功能以后很興奮,他想寫(xiě)個(gè)程序完成同樣的功能,你能幫助他么?

Solution

居然1A【然而看了題解】

查詢(xún)x在y中出現(xiàn)了多少次,即y的節(jié)點(diǎn)有多少可以通過(guò)fail跳到x的尾節(jié)點(diǎn)

但是這個(gè)太暴力了,于是我們建一下fail樹(shù)(fail的反向邊,由fail指針指向原節(jié)點(diǎn))

轉(zhuǎn)化為查詢(xún)x的尾節(jié)點(diǎn)可以從fail樹(shù)到達(dá)的y的節(jié)點(diǎn)有多少個(gè)

然后就可以通過(guò)dfs序和樹(shù)狀數(shù)組做了

離線,對(duì)于相同的y一次性處理,標(biāo)記出所有y的節(jié)點(diǎn),查詢(xún)每一個(gè)x的子樹(shù)中y的節(jié)點(diǎn)的出現(xiàn)次數(shù)

#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #define MAXN 100005 using namespace std; int m,sz,root,pos[MAXN],in[MAXN],out[MAXN],dfn_clock=0,c[MAXN],ans[MAXN],dfn[MAXN]; int head1[MAXN],head2[MAXN],cnt1=0,cnt2=0; struct Node2 {int next,to; }e1[MAXN],e2[MAXN]; void addedge1(int u,int v) {e1[++cnt1].next=head1[u];head1[u]=cnt1;e1[cnt1].to=v; } void addedge2(int u,int v) {e2[++cnt2].next=head2[u];head2[u]=cnt2;e2[cnt2].to=v; } char s[MAXN]; struct Node1 {int next[26],par,fail; }trie[MAXN]; int newnode(int f) {trie[++sz].fail=0;trie[sz].par=f;memset(trie[sz].next,0,sizeof(trie[sz].next));return sz; } void insert() {sz=0,root=newnode(0);int i=0,p=root,_clock=0;while(s[i]){if(s[i]=='B')p=trie[p].par;else if(s[i]=='P')pos[++_clock]=p;else {int idx=s[i]-'a';if(!trie[p].next[idx])trie[p].next[idx]=newnode(p);p=trie[p].next[idx];}i++;} } queue<int>q; void build() {q.push(root);while(!q.empty()){int p=q.front();q.pop();for(int i=0;i<26;i++){int t=trie[p].fail;while(t&&!trie[t].next[i])t=trie[t].fail;if(trie[p].next[i]){trie[trie[p].next[i]].fail=t?trie[t].next[i]:root;q.push(trie[p].next[i]);}else trie[p].next[i]=t?trie[t].next[i]:root;}} } void dfs(int u) {if(dfn[u])return; ++dfn_clock;in[u]=dfn[u]=dfn_clock;for(int i=head1[u];~i;i=e1[i].next)dfs(e1[i].to);out[u]=dfn_clock; } int lowbit(int x){return x&(-x);} void add(int x,int p) {while(p<=sz+1){c[p]+=x;p+=lowbit(p);} } int query(int p) {int res=0;while(p>0){res+=c[p];p-=lowbit(p);}return res; } void solve() {int i=0,p=root,_clock=0;while(s[i]){if(s[i]=='B')add(-1,dfn[p]),p=trie[p].par;else if(s[i]=='P'){++_clock;for(int j=head2[_clock];~j;j=e2[j].next){int t=e2[j].to;ans[j]=query(out[pos[t]])-query(in[pos[t]]-1);}}else{int idx=s[i]-'a';p=trie[p].next[idx];add(1,dfn[p]);}i++;} } int main() {memset(head1,-1,sizeof(head1));memset(head2,-1,sizeof(head2));scanf("%s",s); insert(),build();for(int i=1;i<=sz;i++)addedge1(trie[i].fail,i);scanf("%d",&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addedge2(y,x);}dfs(0);solve();for(int i=1;i<=m;i++)printf("%d\n",ans[i]);return 0; }

?

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

總結(jié)

以上是生活随笔為你收集整理的[BZOJ 2434][Noi2011]阿狸的打字机(AC自动机+树状数组+dfs序)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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