NOI2011 阿狸的打字機

2022-04-29 05:57:11 字數 1492 閱讀 7188

題目鏈結。

雖然總長度我們不能確定,但是如果跟著第一行字串跑建 ac 自動機,節點數肯定 \(\le 10^5\) 的,因為每個字元最多增加乙個節點。

考慮乙個查詢 \((x, y)\), 即把字串 \(s[y]\) 的每個點對應在圖上的點 \(+1\),然後詢問 \(x\) 對應節點的子樹和。

子樹和想到 \(dfs\) 序差分 \(+\) 樹狀陣列

離線,把詢問 \(x\) 打進 \(d[y]\) 裡。 考慮對於每個 \(y\),先修改,然後詢問對應的 \(x\)。這裡的每個字串既是匹配串也是模式串,所以 \(s[y]\) 對應的節點就是一條從根出發的鏈。第二次再跟著輸入的第一行字串跑 \(ac\) 自動機,動態維護將根節點到當前節點上的所有點 \(+1\),遇到乙個 p 就停下來查詢即可。

注意 「b」 退回時,要刪除對應的影響。

\(o((n + m)logn)\)

#include #include #include #include using namespace std;

const int n = 100005;

typedef long long ll;

char s[n];

int n, m, cnt, dfncnt, fail[n], match[n], fa[n], c[n], tr[n][26];

int id[n], ans[n], dfn[n], sz[n], q[n], idx;

// bit

void add(int x, int k)

int ask(int x)

// 詢問 x 的子樹和

int query(int x)

// 詢問

struct q;

vectord[n]; // q[i] 表示插入恰好為 i 個字串需要的詢問

// fail 樹的邊

int head[n], nume = 0;

struct e e[n];

void addedge(int u, int v) ;

head[u] = nume;

}// ac 自動機:插入

void insert() }}

void dfs(int u)

}// 建 fail

void build() else tr[u][i] = tr[fail[u]][i];

} }for (int i = 1; i <= idx; i++) addedge(fail[i], i);

dfs(0);

}void work() else if (s[i] == 'p')

} else }}

int main() );

} insert();

build();

work();

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

return 0;

}

NOI2011阿狸的打字機

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

NOI2011 阿狸的打字機

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

NOI2011阿狸的打字機

剛學完字串演算法做一做題,這道題的質量的確很高,做完以後感覺對ac自動機有長進 一下的神仙思路來自yyb dalao 蒟蒻開始只想到了40分暴力,全程靠題解 step1 首先直接處理出所有的串再裸kmp好寫,但是覺得得分應該不高,也沒有人說能拿多少分 這個題正解的第一步是要想到ac自動機,準確地說和...