JSOI2007 文字生成器(AC自動機 dp)

2021-10-24 06:51:22 字數 1790 閱讀 3349

有 n

nn 個單詞,現在要生成 m

mm 個字母的文字,問至少出現乙個單詞的文字有多少種。

n ≤60

,m

≤100,∣

si∣≤

100n\leq 60,m\leq 100,|s_i|\leq 100

n≤60,m

≤100

,∣si

​∣≤1

00s

is_i

si​ 只包含大寫英文本母。

這算是一道很典型的 acac

ac自動機上 dpdp

dp的題目。

答案就是用 26m

26^m

26m 減去乙個單詞都沒出現過的。現在我們求一下後面的東西。

令 f i,

jf_

fi,j

​ 表示長度為 i

ii,來到節點 j

jj 的方案數。

那麼如果 trj

,k

tr_tr

j,k​

不是末尾節點,就可以轉移到 trj

,k

tr_tr

j,k​

。初始條件 f0,

0=

1f_=1

f0,0​=

1。總複雜度是 o(26

n∣s∣

m)

o(26n|s|m)

o(26n∣

s∣m)

#include

#include

#include

using

namespace __gnu_pbds;

using

namespace std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

struct custom_hash

size_t operator()

(uint64_t x)

const};

ll z =1;

intread()

intksm

(int a,

int b,

int p)

return s;

}const

int mod =

1e4+

7, n =

6e3+5;

int f[

105]

[n], ch[n][26

], fail[n]

, v[n]

, cnt;

char s[n]

;void

insert

(char

*s) v[p]=1

;}void

get_fail()

}}intmain()

get_fail()

; ans =

ksm(

26, m, mod)

; f[0]

[0]=

1;for(i =

0; i <= m; i++)}

}}for(i =

0; i <= cnt; i++

) ans =

(ans - f[m]

[i])

% mod;

printf

("%d"

,(ans + mod)

% mod)

;return0;

}

JSOI2007 文字生成器

用ac自動機處理所有了解的單詞 顯然,不能直接算,直接算的話,我們需要大力容斥,複雜度不允許 我們不妨反過來做,我們根據ac自動機處理出所有的不可行解,然後用總數減去即可 計算所有不可行解用dp,f i j 表示處理到字串第i位,在自動機上第j個節點的不可行方案數,直接暴力轉移即可 include ...

JSOI2007 文字生成器

容斥原理,求出所有的情況減去不可讀的情況就是可讀的文字數了a 找不可讀文字的數量類似於病毒那一題趴我覺得 dp轉移的話.用f i j 表示當前在節點j,且串長為i時的情況 include using namespace std const int mod 1e4 7 const int n 2000...

JSOI2007 文字生成器

對於乙個長度為 n 的串 s 有多少可能情況的串 s 使得 s 的子串中至少包含乙個給定的串,給定的串有 m 個 由多模式串匹配想到ac自動機,由計數想到dp 首先建好trie圖,更新所有end標記。記 dp now st flag 表示當前正在匹配第 st 位,已確定的串匹配到了trie圖上的 n...