求有多少個長度為l,且包含n個串的字串,答案小於等於42時輸出方案。(n<=10,l<=25,|s|<=10)
常規的ac自動機上的壯壓dp,通過fail去掉那些被包含的字串即可。
d p[
i][j
][s]
:dp[i][j][s]:
dp[i][
j][s
]:走了i
ii步,當前在點j
jj,已經走過的串的二進位制為s
ss的方案數。
d p[
i+1]
[ch[
j][c
]][s
∣ed[
ch[j
][c]
]]+=
dp[i
][j]
[s
]dp[i+1][ch[j][c]][s|ed[ch[j][c]]]+=dp[i][j][s]
dp[i+1
][ch
[j][
c]][
s∣ed
[ch[
j][c
]]]+
=dp[
i][j
][s]
a ns
+=dp
[l][
i][s
(全集)
]ans+=dp[l][i][s(全集)]
ans+=d
p[l]
[i][
s(全集
)]由於答案小於等於42才輸出方案,這個時候所有n個字串都是緊密相連的,可以從終止狀態開始搜尋,也可以n!列舉每個字串的相對位置,由於已經去掉了包含關係,所以相鄰的字串之間盡量多的重疊即可。
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 105
#define maxm 1024
#define ll long long
ll dp[30]
[maxn]
[maxm]
,sum;
int ch[maxn][26
],tot,cnt,s,fail[maxn]
,ed[maxn]
;char s[15]
,mem[maxn]
,a[30];
vectorans;
void
insert()
nw=ch[nw]
[c];
} ed[nw]=1
;}queue<
int>q;
void
build()
}for
(int i=
0;i<=tot;i++
) ed[fail[i]]=
0;for(
int i=
0;i<=tot;i++)if
(ed[i]
) ed[i]=1
dfs(
int len,
int pos,
int sta)
int c=mem[pos]
-'a'
;for
(int i=
0;i<=tot;i++)if
(dp[len-1]
[i][sta]
&&ch[i]
[c]==pos)
dfs(len-
1,i,sta);if
(ed[pos])}
intmain()
build()
; s=
1
[0][
0]=1
;for
(int i=
0;i)for
(int j=
0;j<=tot;j++
)for
(int s=
0;s(dp[i]
[j][s]
)for
(int i=
0;i<=tot;i++
) sum+
=dp[l]
[i][s-1]
;printf
("%lld\n"
,sum);if
(sum<=42)
}
AC自動機 玄武密碼
題目鏈結 題意 對於每一段文字,其字首在母串上的最大匹配長度是多少呢 參考別人的題解 我們只需要先建立所有密碼的trie樹 再以母串為主串跑乙個ac自動機 不過其中還是有一些需要改動的地方 原本字典樹中用來記錄某個節點是不是字串結尾的陣列不需要,直接刪去 我們需要另乙個陣列來標記哪些點被匹配 跑完a...
AC自動機 建立nlogn個AC自動機
string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...
AC自動機及字尾自動機
ac自動機是一種基於trie樹的演算法,其本質和kmp上的處理很相似。trie樹結構 kmp轉移思路 ac自動機組要由三個部分組成 trie樹的建立 fail指標的匹配 對ac自動機的詢問 每次建立自動機會有一次初始化 ac自動機類 struct node node結構體 struct ac voi...