題解 NOI2011 阿狸的打字機

2022-04-29 21:39:15 字數 1443 閱讀 5839

阿狸的打字機

\(\text\)

所以,我們可以對操作串進行模擬,並處理出每乙個串在樹上的位置。

接下來,我們考慮如何處理詢問。\(y\)是需要跑的串,於是我們應按照\(y\)排序以保證在處理這個\(y\)之前,它本身或者其他的東西沒有加進樹上過。

考慮同樣的模板處理方法:對於乙個串出現了幾次,我只需要統計這個串結尾編號在\(fail\)樹子樹中的\(cnt\)個數。

於是自然想到維護子樹和的有利**:\(dfs\)序和樹狀陣列。

於是,我們可以預先處理掉\(dfs\)序,並直接模擬在\(opt\)串上進行的移動操作即可。

這裡解釋模板的處理思路:首先,既然我們跳到了這個\(fail\)指標,說明我們一定匹配完過當前這整個\(fail\)指標(參考定義)。

觀察\(fail\)樹上的結構,我們結合上面所述可以知道,所有直接或間接指向\(x\)這個節點的\(fail\)指標,只要跳到了,就一定匹配到過整個串\(x\).

於是,我們可以統計\(fail\)樹上\(x\)子樹中的\(cnt\),注意每匹配到乙個點,應該在\(fail\)樹上把從它到根節點的路徑上全部加\(1.\)但實際上我們只需要在匹配到的時候對它單點\(+1,\)再\(dfs\)一下\(fail\)樹就可以了。

#includeusing namespace std;

const int maxn=2000100;

int tot,tr[maxn],fa[maxn];

int pos[maxn],num;

struct treet[maxn];

vectorto[maxn];

struct quq[maxn];

inline bool cmp(qu a,qu b)

} while(!q.empty())

else t[u].ch[i]=t[t[u].fail].ch[i];

} to[t[u].fail].push_back(u);

} //建立ac自動機並建立fail樹

}int dfn[maxn],i,ed[maxn];

void dfs(int u)

inline int lowbit(int x)

inline void add(int x,int v)

inline int query(int x)

//樹狀陣列不解釋

int ans[maxn],m;

int main()//刪掉當前u所在字元

else//更新下乙個字元

l++;//操作串後移

} ans[q[i].id]=query(ed[pos[q[i].x]])-query(dfn[pos[q[i].x]]-1);//注意雙對映!

} for(int i=1;i<=m;++i)printf("%d\n",ans[i]);

return 0;

}

題解 NOI2011阿狸的打字機

problem bzoj2434 洛谷2414 codevs1946 solution 本著刷ac自動機去做的這題,而且這題一看就是要用資料結構的 這題大致題意是求a在b中出現的次數,聯想ac自動機 如果每次儲存一下列印出來的字串,陣列君會受不了的 首先考慮優化空間,構造ac a c自動機時只儲存每...

NOI2011阿狸的打字機

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

NOI2011 阿狸的打字機

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