2434 Noi2011 阿狸的打字機

2021-08-15 10:45:59 字數 1397 閱讀 2078

題目鏈結

題目大意:初始字串為空,首先給定一系列操作序列,有三種操作:

1.在結尾加乙個字元

2.在結尾刪除乙個字元

3.列印當前字串

然後多次詢問第x個列印的字串在第y個列印的字串中出現了幾次

題解:建出trie……

新增乙個字元->新建乙個子節點(若存在在不用新建),進入該子節點

刪除乙個字元->返回到父親節點

列印當前字串->在當前節點標記是第幾個列印串

跑出fail指標

對於ac自動機上的兩個子串u,v(ac自動機上的子串x可以看成是從根節點到節點x連成的乙個字串),u是v的子串等價於u是v某個字首的字尾,而判斷u是x的字尾只需要看x能否沿著fail指標走到u

所以查詢u在v中出現的次數即為查詢根結點到v的路徑中有多少個x,能沿著fail指標走到u

fail指標沒有環 每個節點只有乙個出度 那麼反向之後顯然是一棵樹,x沿著反向fail邊走到的點構成x的子樹

那麼查詢(u,v)時,把root->v的路徑上的點賦值為1,答案可以通過查詢x的子樹和解決,dfs序上單點修改區間求和就可以了

但是不能直接暴力改……需要採用一些方法減少修改次數

離線,按照v排序,這樣就可以根據原來建立ac自動機的順序進行修改了…………只需要進入時+1,離開時-1,查詢時自然root->v的路徑上的每乙個點都是1了

我的收穫:ac自動機~~

#include 

using

namespace

std;

const

int n=100015;

int m;

int t,head[n];

int tim,in[n],out[n];

int cnt,pos[n],ans[n];

char s[n];

vector

g[n];

struct quesa[n];

bool cmp(ques a,ques b)e[n];

void add(int u,int v)

struct bit

}tree;

struct ac_dfa}}

void getfail()

for(int i=1;i<=tot;i++) g[fail[i]].push_back(i);

}void dfs(int x)

}else

if(s[i]=='b') tree.updata(in[x],-1),x=fa[x];

else x=c[x][idx],tree.updata(in[x],1);}}

}ac;

void work()

void init()

int main()

BZOJ2434 NOI2011 阿狸的打字機

發現一種新的思路,以前從來沒有見過的,即ac自動機的fail樹。這一題我們先考慮暴力,從root往y的最後乙個點走,如果走到了x的末點,ans 如果通過fail指標走到了x的末點,ans 反過來考慮,從x的末點開始,如果當前點在y串或者通過反向的fail到了y串,ans 又發把fail反向之後得到的...

bzoj2434 Noi2011 阿狸的打字機

傳送門 description 阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。經阿狸研究發現,這個打字機是這樣工作的 l 輸入小寫字母,打字機的乙個凹槽中會加入這個字母 這個字母加在凹槽的最後 l 按一下印有 b ...

bzoj 2434 Noi2011 阿狸的打字機

time limit 10 sec memory limit 256 mb submit 3139 solved 1731 submit status discuss 阿狸喜歡收藏各種稀奇古怪的東西,最近他淘到一台老式的打字機。打字機上只有28個按鍵,分別印有26個小寫英文本母和 b p 兩個字母。...