BZOJ3277 串 廣義字尾自動機

2021-09-07 18:56:21 字數 1690 閱讀 9459

time limit: 10 sec  memory limit: 128 mb

submit: 1196  solved: 478

[submit][status][discuss]

字串是oi界常考的問題。現在給定你n個字串,詢問每個字串有多少子串(不包括空串)是所有n個字串中

至少k個字串的子串(注意包括本身)。

第一行兩個整數n,k。

接下來n行每行乙個字串。

n,k,l<=100000

輸出一行n個整數,第i個整數表示第i個字串的答案。

3 1abcaab

6 1 3

廣義字尾自動機?就是把一坨字串建到乙個字尾自動機上??

不過好難理解啊qwq。。

對於這題,首先我們要知道幾個定理

1.節點$i$表示的本質不同的字串可以由$len[i] - len[fa[i]]$得到

2.乙個串的子串 等價於 乙個串所有字首的所有字尾

這樣子串就轉換為求乙個串的字首的所有字尾的問題

字首可以列舉,問題轉換為求乙個字串的各個字尾在其他字串**現了多少次

這樣我們可以把廣義字尾自動機建出來,然後暴力沿著$parent$邊跑,這樣可以列舉出所有字尾

同時為了不重複列舉,我們需要記錄下每個字尾是否已經被列舉過了

這樣我們就可以知道乙個狀態出現的次數是否$>= k$,接下來我們只要統計出這個狀態出現的次數就行了

根據定理$1$,這個很好統計

然後就做完啦

#include#include

#include

using

namespace

std;

const

int maxn = 1e6 + 10

;string

s[maxn];

intn, k;

int fa[maxn], len[maxn], ch[maxn][26], root = 1, last = 1, tot = 1

, times[maxn];

void insert(int

x)

}}int

vis[maxn], sum[maxn];

void gettimes()

}}void dfs(int

x) int

main()

gettimes();

for(int i = 1; i <= tot; i++) sum[i] = (times[i] >= k) * (len[i] - len[fa[i]]);//

i狀態所表示的子串集合對答案的貢獻

memset(vis, 0, sizeof

(vis));

for(int i = 1; i <= tot; i++) dfs(i);

for(int i = 1; i <= n; i++)

return0;

}

bzoj 3277 串 (廣義字尾自動機)

time limit 10 sec memory limit 128 mb submit 357 solved 144 submit status discuss 字串是oi界常考的問題。現在給定你n個字串,詢問每個字串有多少子串 不包括空串 是所有n個字串中至少k個字串的子串 注意包括本身 第一行...

BZOJ 3277 串 廣義字尾自動機

判斷乙個串是否在至少k個字串裡面的方法後3473一樣,每新增乙個新的字元就沿fail鏈更新。剩下的問題就只是剩下了,每增加乙個新的字元,共多出現了多少個新的字串,如果不要求重複,那麼很顯然就是len u len fail u 這裡重複的字串也需要加入答案所以只用沿fail鏈dfs一下,sum u f...

bzoj3277 串 廣義字尾自動機

廣義字尾自動機板子題 廣義字尾自動機的建圖方法大概就是在trie上按bfs序來建圖,這裡的last節點應該是trie上父親的last節點 然後這裡按題目要求記right為在至少k個串走過的方案,具體建法就是先把每個串跑一遍然後在parent樹上更新所有父親節點的答案,注意不要判重。然後掃一遍所有節點...