簡要題意:給出m
mm個病毒串,問你由atg
catgc
atgc
構成的長度為 n
nn 且不包含這些病毒串的字串有多少個?
定義d p[
i][j
]=dp
[當前長
度為i]
[當前在
ac自動
機的第j
個節點]
=方案數
dp[i][j]=dp[當前長度為i][當前在ac自動機的第j個節點]=方案數
dp[i][
j]=d
p[當前
長度為i
][當前
在ac自
動機的第
j個節點
]=方案
數.轉移方程也十分簡單.
但是注意到n
nn的大小,顯然會t到飛起,考慮矩陣乘法優化,其實再轉化一下題意就是:全圖中的0
00節點到其他節點剛好經過n
nn步的方案數(求從a
aa點到b
bb點剛好經過n
nn步的方案數).
那麼將整幅圖轉化為鄰接矩陣,然後對矩陣快速冪即可.
未優化
#include
//未優化
#define m 2009
#define int long long
using
namespace std;
intread()
for(
;isdigit
(ch)
;ch=
getchar()
) re=
(re<<3)
+(re<<1)
+ch-
'0';
return re*f;
}int fail[m]
,val[m]
,cnt,f[m]
[201
],n,m,tr[
201][4
],ans;
char s[20]
;void
build()
val[u]=1
;}void
getfail()
}}}voiddp(
)for
(int i=
0;i<=cnt;i++
) ans+
=f[n]
[i];
printf
("%lld\n"
,ans);}
signed
main()
getfail()
;dp()
;return0;
}
已優化
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define m 209
#define int long long
using
namespace std;
intread()
for(
;isdigit
(ch)
;ch=
getchar()
) re=
(re<<3)
+(re<<1)
+ch-
'0';
return re*f;
}int fail[m]
,val[m]
,cnt,n,m,tr[m][4
],sum;
const
int mod=
1e5;
char s[20]
;struct matrix
matrix operator*(
const matrix &b)
const
}base,ans;
void
build()
val[u]=1
;}void
getfail()
}}}void
init()
}ans.a[0]
[0]=
1;}void
ksm(
int b)
}voiddp(
)signed
main()
getfail()
;dp()
;return0;
}
poj2778 ac自動機 矩陣快速冪
poj2778 求長度為m且不包含n個子串的種類數.參考自這個部落格.ac自動機 矩陣快速冪.這兒有個結論.給定乙個有向圖,問從a點恰好走k步 允許重複經過邊 到達b點的方案數mod p的值 把給定的圖轉為鄰接矩陣,即a i,j 1當且僅當存在一條邊i j。令c a a,那麼c i,j a i,k ...
poj2778 ac自動機 矩陣快速冪
給m個子串,求長度為n的不包含子串的母串數,最直接的應該是暴搜,肯定tle,考慮用ac自動機 將子串建成字典樹,通過next表來構造矩陣,然後用矩陣快速冪求長度為n的數量 鄰接矩陣 對於a i,j k 是指從i到j經過k個點的所有情況數 注意對於end陣列,如果某個節點如果fail指標end陣列為1...
poj2778(AC自動機 矩陣快速冪)
題意 給你n個字串,問你長度為m的字串且字串中不含有那n個子串的字串的數量 解題思路 這道題一開始就不太懂,還以為是組合數學的題目,後面看了別人的部落格,才知道這是屬於ac自動機的另一種用法,是關於fail陣列的運用,因為題目問的是不允許包含那n個字串,所以我們可以這麼想,假設乙個trie樹每個結點...