POJ2778 AC自動機,矩陣快速冪優化DP

2021-10-08 14:25:44 字數 2316 閱讀 5064

簡要題意:給出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樹每個結點...