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 ...