題目問,給定 n
nn 個模式串,問你主串的 「可理解的」 最長字首長度。「可理解的」 意思指可以被分成若干個模式串。
首先我們知道ac自動機,fai
lfail
fail
指標跳轉的是相同字尾,在跳轉的過程中會依據長度從大到小經過相同的字尾。比如 abc
d−
−>bc
d−
−>
dabcd -- >bcd - ->d
abcd−−
>bc
d−−>d。
在該題中,假設主串當前長度為 k
kk 的字尾,可以在 fai
lfail
fail
樹上找到乙個以該字元為結束的長度相同的字尾,則可以發生 f[i
]=f[
i]
f[i]=f[i]
f[i]=f
[i]∣|∣f
[i−k
]f[i-k]
f[i−k]
的狀態轉移,f
ff 表示可以「可理解」。
那麼我們要對於不同長度的字尾都做乙個狀態轉移,則需要做個狀態壓縮,因為模式串長度 ∣s∣
≤10
|s|\leq10
∣s∣≤10
,所以我們可以用 int
intin
t 型資料,以二進位制來表示。
我們在建自動機時做預處理,維護乙個 dpdp
dp陣列,用於存貯模式串的狀態,先繼承 fai
lfail
fail
指標跳轉的所有字尾狀態。且當前若為結束位置,則將自身狀態加入其中。
**如下:
#include
#define endl '\n'
using
namespace std;
typedef
long
long ll;
const
int maxn =
2e6+5;
const
int lens =
2e4+5;
int cnt;
int tr[lens][26
], isend[lens]
, fail[lens]
;int dp[lens]
, depth[lens]
;char mo[
200]
[200
], text[maxn]
;void
insert
(char s,
int no)
isend[p]++;
}void
build()
while
(!q.
empty()
)else
tr[k]
[i]= tr[fail[k]
][i];}
}}intmain()
build()
;while
(m--)}
cout << ans << endl;
}}
洛谷 P 2292 L語言 AC自動機
一道比較簡單的題,結果自己腦補了各種奇葩 錯誤 的判斷,搞了乙個多小時。題意 用已知字典去識別乙個串,求最長可識別字首 指能將此字首分解為字典裡面的單詞 思路 建好ac自動機,記錄好每個點所代表的字串的長度 拿要匹配的串從前往後匹配,若某個點完全不能匹配,直接退出 可以不考慮這個 處理好什麼叫 可以...
AC自動機 洛谷P3808 AC自動機(簡單版)
給定 n n 個模式串和1個文字串,求有多少個模式串在文字串裡出現過 多模匹配用ac role presentation aca c自動機 首先建造一棵字典樹,新增所有模式串,然後建造失配指標,最後進行匹配 luogu judger enable o2 include include include...
AC自動機入門,洛谷P3808
給定n個模式串和1個文字串,求有多少個模式串在文字串裡出現過。輸入輸出格式 輸入格式 第一行乙個n,表示模式串個數 下面n行每行乙個模式串 下面一行乙個文字串。輸出格式 乙個數表示答案 輸入輸出樣例 輸入樣例 1 2aaa aa輸出樣例 1 兩個會出現在模板題面裡的詞語 文字串和模式串 給你幾個單詞...