ac自動機
ac自動機,說白了就是在
trie
樹上跑kmp
(其實個人感覺比
kmp容易理解)。是一種多匹配串,單個主串的匹配。概括來說,就是將多個匹配串構造乙個
trie
樹,對於每個
trie
樹的節點構造
nxt指標,最後把主串放在上面跑。
構造trie樹
和普通的
trie
樹構建一樣,沒有什麼區別
inline void insert(char *s)構造nxt陣列其實這一部分是isend[u]++;//
注意isend的具體處理根據題目而定
return
;}
ac自動機的核心,我們這樣構造:對於每個節點,它的nxt是,它父親的nxt的和它名字相同的兒子。如圖,
u的父親是
v,它父親的
nxt的
a這個兒子就是u的
還有一種情況,就是如果節點
u,它的沒有
a這個兒子,那麼它就要把
nxt[u]的a
這個兒子當成他的兒子。
如圖,因為u沒有
a的子節點,所以就連到
nxt[u]的a
子節點。
那麼這麼做的原因是什麼?我們來看一下這個圖:
如圖,這個
trie
樹中前7
個節點的
next
都已經構造完成了(箭頭表示他們的
nxt,1的
nxt是
0,沒有畫出來)
.現在要找8的
next
。按照「它的nxt是,它父親的nxt的和它名字相同的兒子」的原則,我們找到
8的父親,
7,發現7的
nxt,
5也沒有
b這個兒子,這時候我們需要找5的
next,2
,最終發現2有
b兒子,是4,將
8連到4。
但是注意,其實我們這乙個乙個找nxt是可以省略的。如果按著剛才「因為u沒有
a的子節點,所以就連到
nxt[u]的a
子節點。」樹就會變成這樣(黑線表示連邊,紅線表示
5因為沒有
b兒子,就把他的
nxt:2,的
b兒子:
4,當成自己的兒子,
7也同理,因為它沒有
a兒子,所以把他的
nxt的
a兒子:
2,當成自己的
a兒子。再來看
8,發現它的父親的
nxt,5,的
b兒子是
4,所以自己的
next就是4
了。這樣減少了剛才乙個乙個找
nxt的步驟。
inline void getnxt()}}查詢查詢的具體實現是根據題目而定,我就拿這道題舉個例子:給一大堆匹配串和乙個主串,求有多少個匹配串在主串上出現過。return
;}
這種題的做法就是現在構建
trie
樹的時候,把每個單詞的結尾都記錄一下:
isend[i]++
。最後跑一遍
ac自動機,到每乙個節點是
ans+=isend[i];isend=0;
這樣聽起來很簡單,那麼怎麼遍歷
ac自動機呢?
迴圈遍歷主串s,令
u表示當前點,每當主串
s到下一位時,
u=tree[u][s[i]-『a』]
(就是等於它的兒子)。然後對於每個
u,迴圈它的
nxt直到根。每到乙個點就
ans+=isend
。具體看**:
inline void總結再來回顧一下search()
k=nxt[k];
}u=tree[u][c];//
遍歷到它的兒子。
} printf(
"%d\n
",ans);
}
ac自動機的步驟:構建
trie
樹,構建
next
陣列,查詢。其中
next
有兩個原則:1、當這個節點沒有字元c這個兒子時,把自己的next的c這個兒子當做自己的兒子
2、自己兒子的nxt等於自己nxt的兒子
附上**:#include
#include附加:可持久化ac自動機如果你希望每當你查詢到乙個字串,然後要把它刪去時,就需要可持久化#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define maxn 100010
#define inf 10000009
#define mod 10000007
#define ll long long
#define in(a) a=read()
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define drep(i,k,n) for(int i=k;i>=n;i--)
#define cl(a) memset(a,0,sizeof(a))inline
intread()
inline
void
out(int
x)int
t,n;
int total=1
;int nxt[1000010],tree[500010][26
];char
in[55
];int isend[1000010
];char t[1000010
];queue
q;int calc(char
c)inline
void insert(char *s)
isend[u]++;
return;}
inline
void getnxt()}}
return;}
inline
void
search()
k=nxt[k];
}u=tree[u][c];//遍歷
到它的兒子。
} printf(
"%d\n
",ans);
}int
main()
scanf("%s
",t);
getnxt();
search();
}return0;
}
ac自動機。其實和普通的
ac自動機很像,唯一區別是查詢的時候去掉了對於每乙個u遍歷
nxt直到根的步驟,然後讓每個
u都壓進棧,遇到
end就彈出棧裡面此字串長度的元素。
AC自動機詳解
最近真是太頹了,做了一堆板子題,現在對一些知識點順便來個總結記錄 大家應該都知道kmp和trie樹吧,不懂的可以看我部落格或到網上自己動手尋找資料。ac自動機是乙個很好的東西,這是因為它的名字很好它能夠在有多個模式串的時候進行全文匹配,這十分方便地擴充套件了kmp的功能,實際上它的思路與原理與kmp...
AC自動機詳解
首先,ac自動機,不是 自動accepted機,這是乙個多模字串匹配演算法,學習這個演算法,首先要熟悉kmp演算法這個單模字串匹配演算法,然後,我們知道有個高效的多模字串匹配演算法,叫字典樹,它處理的是一些單詞在乙個句子裡出現了幾次,但假如不是在乙個句子裡,而是在乙個字串裡呢?那它就顯得很弱了,所以...
AC自動機詳解
include include include include include include include include using namespace std typedef long long ll const int maxn 2 1e6 9 int trie maxn 26 字典樹 i...