AC自動機學習筆記

2021-10-08 10:25:53 字數 4128 閱讀 1300

ac自動機是基於字典樹和fail指標來快速一類解決多串匹配的問題。

先用所有模式串建乙個字典樹。然後用bfs搞出每個節點的fail指標。

fail指標是指向 和當前 字首的字尾有最長匹配的字首。

洛谷3808

掃文字串的時候,標記一下訪問過的字典樹上的節點。。

#include

using

namespace std;

typedef

long

long ll;

const

int n =

1e6+10;

#define fi first

#define se second

#define pb push_back

#define mp make_pair

#define wzh(x) cerr<<#x<<' 'char a[n]

,b[n]

;struct ac

void

clear

(int o)}}

void

insert

(char

*a,int n)

o=tr[o]

[a[i]

-'a'];

} ta[o]++;

}void

build()

else

if(tr[f]

[i])fa[tr[x]

[i]]

=tr[f]

[i];

else fa[tr[x]

[i]]=1

;}q.

push

(tr[x]

[i]);}

}}// for(int i=1;i<=cnt;i++)cout<}

intsolve

(char

*a,int n)

if(tr[o]

[a[i]

-'a'

])o=tr[o]

[a[i]

-'a'];

else o=1;

int f=o;

while

(ta[f]!=-

1)}return res;

}}g;

intmain()

g.build()

;scanf

("%s"

,b+1);

printf

("%d\n"

,g.solve

(b,strlen

(b+1))

);return0;

}

洛谷3796

因為這個模式串的深度最多70,就是說字典樹的深度不超過70.

那掃文字串的時候可以直接暴力跳fail,記錄訪問到的點訪問的次數。

#include

using

namespace std;

typedef

long

long ll;

const

int n =

1e6+10;

#define fi first

#define se second

#define pb push_back

#define mp make_pair

#define wzh(x) cerr<<#x<<' 'void

clear

(int o)}}

intinsert

(char

*a,int n,

int now)

o=tr[o]

[a[i]

-'a'];

} ta[o]++;

return o;

}void

build()

else

if(tr[f]

[i])fa[tr[x]

[i]]

=tr[f]

[i];

else fa[tr[x]

[i]]=1

;}q.

push

(tr[x]

[i]);}

}}}void

solve

(char

*a,int n)

if(tr[o]

[a[i]

-'a'

])o=tr[o]

[a[i]

-'a'];

else o=1;

int f=o;

while

(f!=1)

}}}g;int n,d[n]

,c[n]

;char a[

155][77

],b[n]

;int

main()

g.build()

; cin>>b+1;

g.solve

(b,strlen

(b+1))

;sort

(d+1

,d+1

+n,(

int x,

int y));

int l=1;

while

(l+1

<=n&&g.vis[c[d[l+1]

]]==g.vis[c[d[l]]]

)l++

; cout<]]

<<

'\n'

;for

(int i=

1;i<=l;i++

) g.

clear(1

);}return0;

}

洛谷5357

就在fail樹上求一下子樹和即可。。

#include

using

namespace std;

typedef

long

long ll;

const

int n =

2e6+10;

#define fi first

#define se second

#define pb push_back

#define mp make_pair

#define wzh(x) cerr<<#x<<' 'void

clear

(int o)}}

intinsert

(char

*a,int n)

sz[cnt]=0

; o=tr[o]

[a[i]

-'a'];

}return o;

}void

build()

else

if(tr[f]

[i])fa[tr[x]

[i]]

=tr[f]

[i];

else fa[tr[x]

[i]]=1

;}v[fa[tr[x]

[i]]].

pb(tr[x]

[i])

; q.

push

(tr[x]

[i]);}

}}}void

solve

(char

*a,int n)

if(tr[o]

[a[i]

-'a'

])o=tr[o]

[a[i]

-'a'];

else o=1;

int f=o;

sz[f]++;

}}intget

(int x)

}}g;

int n,ti[n]

;char a[n]

,b[n]

;int

main()

g.build()

;scanf

("%s"

,b+1);

g.solve

(b,strlen

(b+1))

;// cout<<"ok"get(1)

;for

(int i=

1;i<=n;i++

)printf

("%d\n"

,g.sz[ti[i]])

;return0;

}

AC自動機 學習筆記

是一種數學模型,大概就是由一堆狀態和狀態轉移規則等東西構成,能與外界交換資訊,並改變動作。這個是理論上的東西,了解就行,對ac自動機的理解沒有大影響。通俗的講就是在trie上做kmp,處理多模式串匹配問題。trie 的每個結點就是乙個狀態,根結點是初始狀態。ac自動機的行為被定義為一下3個函式 1....

AC自動機學習筆記

title ac自動機學習筆記 date 2020 08 31 15 53 40 tags 8月的最後一天,還是完成了ac自動機的學習。在熟練掌握了kmp後,我發現ac自動機並沒有想象的那麼難,既不難理解,也不難實現,於是決定寫點東西記錄一下。本篇主要談談ac自動機的理論,思想。首先我們必須要明確乙...

AC自動機學習筆記

先簡單複習一下學習ac自動機所需要的字首知識。字首知識 1 trie樹 字典樹,也稱trie樹,字首樹,主要用於儲存大量的字串以及查詢操作。對於trie樹,一般有兩個操作 舉個例子,對於這樣幾個字串,我們看他們在trie樹中是如何儲存的 這裡需要注意,字元是邊,而不是節點,但都是一一對應的 int ...