校內模擬 耍望節(倍增)(KMP)

2021-09-29 08:45:50 字數 3409 閱讀 3700

簡要題意:

給你乙個殘缺的串s

ss,裡面有一些空位,你需要填充裡面的空位使得t

tt是s

ss的字串。

多次詢問字典序第k

kk小的填充方案,輸出雜湊值。

倍增裸題。

反正我這輩子都在考場上寫不出字典序倍增

考慮建立kmp自動機,狀態[i]

[j

][i][j]

[i][j]

表示已經決定了前i−1

i-1i−

1個字元的填充,當前匹配到了第j

jj個字元。

選擇siz最大的節點作為後繼節點。

預處理倍增後在kmp自動機的位置,倍增需要跳的rk,倍增過程中的雜湊值。

然後大力倍增就行了。

估計沒有誰跟我一樣考場上寫了結構體沒調出來。。。

**:

#include

#define ll long long

#define re register

#define cs const

namespace io

inline

charpk(

)int

get_s

(char

*s)chargs(

)template

<

typename t>t get()

inline

intgi()

inline ll gl()

}using

namespace io;

using std::cerr;

using std::cout;

template

<

typename t>

void

ckmin

(t &a,t b)

cs int mod=

1e9+7;

inline

intadd

(int a,

int b)

inline

intdec

(int a,

int b)

inline

intmul

(int a,

int b)

inline

void

inc(

int&a,

int b)

inline

void

dec(

int&a,

int b)

inline

void

mul(

int&a,

int b)

cs int n=

5e4+7;

cs ll inf=

1e18

+1e7

;int pw[n]

,n,q,m;

char s[n]

,t[n]

;int nxt[22]

;//kmp

int to[22]

[22];

//kmp自動機

int suf[n]

;//字尾雜湊值

int c0[n]

;std::vector<

int> vec[n]

,zero;

struct statest[n][22

];bool vis[n][22

];//到了第i個位置,第i個位置還沒有決策,當前在kmp自動機的第j的位置上面的狀態轉移

//找到第乙個能夠接納它的kmp終止位置,然後按照排名在後面空位填數

//倍增過程除了最後一步,其餘都不經過kmp終止位置。

void

dfs(

int i,

int j)

int son=

0;ll siz=0;

for(

int re c=

0;c.size()

;++c)

st[i]

[j].son=vec[i]

[son];if

(st[i]

[j].siz==0)

return

; st[i]

[j].rk[0]

=st[i]

[j].pre[son]

; st[i]

[j].h[0]

=mul

(vec[i]

[son]

,pw[n-i]);

st[i]

[j].ps[0]

=to[j]

[vec[i]

[son]];

for(

int re p=

1;p<=16;

++p)

}void

work

(int i,

int j,ll rk,

int hs)

for(

int re p=16;

~p&&j!=m;

--p)}if

(j==m)

cout<"\n"

;return;}

for(

int re c=

0;c.size()

;++c)}}

void

solve()

vec[i]

.push_back

(s[i]^48

);c0[i]=0

;}else

}suf[n+1]

=0;for

(int re i=n;i;

--i)

for(

int re i=

2,j=

0;i<=m;

++i)

memset

(to,0,

sizeof to)

; to[0]

[t[1]^

48]=1

;for

(int re i=

1,k;i<=m;

++i)if(

!to[i]

[t[k+1]

^48])

to[i]

[t[k+1]

^48]=k+1;

}for

(int re i=

1;i<=n+1;

++i)

memset

(st[i],0

,sizeof st[i]);

st[n+1]

[m].siz=1;

memset

(vis,0,

sizeof vis)

;dfs(1

,0);

while

(q--

)work(1

,0,gl

(),0

);}signed

main()

校內模擬 鎖

沒有標籤是因為我真的不知道這算什麼型別 這題我說不來大意你們還是看題面描述吧 小z住的房子一共有n個人,他們每人有乙個重要度。房子的門上可以裝若干把鎖。假設共有k把鎖,命名為1到k。每把鎖有一種對應的鑰匙,也用1到k表示。鑰匙可以複製若干份並發給任意多個居民。每個人都可以持有若干鑰匙,可以不持有鑰匙...

校內模擬 assignment(DP)

題面見校內oj4693 考慮預處理f k i j f k i j f k i j 表示最長的一段不超過k kk的時候,將長度為i ii的序列分為j jj段的方案數。在k kk相同的狀態之間轉移,顯然有f i j f i 1 j f i 1 j 1 f i k 1 j 1 f i j f i 1 j ...

2019 10 03 校內模擬

內網傳送門 很明顯的乙個網路流。轉換一下題意,相當於求保留航線的最大值。所以我們把邊權取負跑最小費用流。有乙個坑點,就是我們只需要費用最小,不要求流量最大,所以不應該用最小費用最大流。有兩個解決辦法 用最小費用可行流。連 i,t,1,0 i,t,1,0 i,t,1 0 的邊,表示不選 i ii 連出...