點此看題
弱化版:[ahoi2005]病毒檢測
先把*
當成分割符,這樣帶萬用字元的串就被劃分成了若干個小串,我們對於每乙個小串在去另乙個串中匹配。
對於每乙個小串,以?
為分割符,將它插入ac
\text
ac自動機中,標記終止節點,把在小串中的終止位置存在ed[
x]
ed[x]
ed[x
]中(型別為vec
to
rvector
vector
),然後我們把乙個點在fai
lfail
fail
樹上到根的路徑的eded
ed全部合併到這個點上(方便查詢)。匹配另乙個串時,對於匹配到的位置i
ii,在自動機上訪問到了節點x
xx,我們把cnt
[i−e
d[x]
[j]+
1]++
cnt[i-ed[x][j]+1]++
cnt[i−
ed[x
][j]
+1]+
+,相當於標記可能的起始位置,匹配完後掃一遍cnt
cntcn
t,如果某個位置被標記的次數等於插入自動機的段數,那麼這個位置就可以作為大的匹配起始點。
本演算法的時間複雜度依賴於萬用字元個數。注意要考慮開始和結束的位置有沒有*
,需要特殊判斷,具體實現可以看**:
#include
#include
#include
#include
using
namespace std;
const
int m =
100005
;int
read()
int t,n,m,beg,end;
char s[m]
,t[m]
;struct automaton
void
ins(
int l,
int r,
int id)
ed[now]
.push_back
(id);}
void
build()
}int
find
(int l,
int r,
bool f,
bool e)
build()
;for
(int i=
1,now=
0;i<=n;i++
)for
(int i=
1;i<=n;i++)if
(cnt[i]
==seg)
return0;
}}ac;
intmain()
i=pos;pd=0;
}if(!flag)
puts
("yes");
else
puts
("no");
}}
bzoj3507 Cqoi2014 萬用字元匹配
我們將題目輸入的那個含萬用字元的串,記為 萬用字元串 下面的檔名記為 檔名 檔名 數量很少可以依次查詢。我們先將 萬用字元串 以 為界,將 萬用字元串 分解,得到若干子串,記為 通配子串 我們將每個 通配子串 各建立乙個 ac自動機。而有的 通配子串 可能含 萬用字元,我們將再次按 為界,分解這個 ...
BZOJ3507 Cqoi2014 萬用字元匹配
必須要記住字串很好卡一不小心就o n 別問我為什麼這麼說.qaq 這題首先滿足位數與字母兩個限制,那麼我們 分大塊?分小塊,求各塊hash值,同時預處理出來每個字串的字首hash這樣就可以o 1 對比了 千萬不要忘記hash字串對比的功能,我在考試的時候一腦抽就忘了.include include ...
bzoj3570 Cqoi2014 萬用字元匹配
題目鏈結 給出乙個主串,裡面有些萬用字元,可以代替任意字串或者消失,可以且僅可以代替乙個字元。問能否用這個串匹配一些詢問串。也許我zz了,半天寫不出 f i j 表示主串到第 i 個匹配符,詢問串到第 j 個字元能否被匹配。轉移很簡單,hash一下就好了。在主串末尾新增乙個 bzoj3507 inc...