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樹上更新所有父親節點的答案,注意不要判重。然後掃一遍所有節點...