玄武密碼(bzoj4327)(JSOI2012)

2022-04-28 18:00:08 字數 2223 閱讀 4082

題目描述

原題來自:jsoi 2012

在美麗的玄武湖畔,雞鳴寺邊,雞籠山前,有一塊富饒而秀美的土地,人們喚作進香河。相傳一日,一縷紫氣從天而至,只一瞬間便消失在了進香河中。老人們說,這是玄武神靈將天書藏匿在此。

很多年後,人們終於在進香河地區發現了帶有玄武密碼的文字。更加神奇的是,這份帶有玄武密碼的文字,與玄武湖南岸台城的結構有微妙的關聯。於是,漫長的破譯工作開始了。

經過分析,我們可以用東南西北四個方向來描述台城城磚的擺放,不妨用乙個長度為 nnn 的序列來描述,序列中的元素分別是eswn,代表了東南西北四向,我們稱之為母串。而神秘的玄武密碼是由四象的圖案描述而成的 mmm 段文字。這裡的四象,分別是東之青龍,西之白虎,南之朱雀,北之玄武,對東南西北四向相對應。

現在,考古工作者遇到了乙個難題。對於每一段文字,其字首在母串上的最大匹配長度是多少呢?

輸入格式

第一行有兩個整數,nnn 和 mmm,分別表示母串的長度和文字段的個數;

第二行是乙個長度為 nnn 的字串,所有字元都滿足是eswn中的乙個;

之後 mmm 行,每行有乙個字串,描述了一段帶有玄武密碼的文字。依然滿足,所有字元都滿足是eswn中的乙個。

輸出格式

輸出有 mmm 行,對應 mmm 段文字。

每一行輸出乙個數,表示這一段文字的字首與母串的最大匹配串長度。

樣例樣例輸入

7 3

snnssns

nnss

nnnwsee

樣例輸出

4

20

資料範圍與提示

對於全部資料,1≤n≤10^7,1≤m≤10^5,保證每一段文字的長度均小於等於 100。

題目描述和題其實莫得關係

上來很自然的想到了kmp

然後發現o(n*100m)會t

然後發現了ac自動機的正解,很sb的寫了一上午(最主要的是教練一直說這次初賽分數線提高了,慌得一批)

首先我們建樹,然後把主串放在上面跑,很顯然,對於每乙個字首如果能夠成功匹配,那麼它的nxt肯定也可以

對於每乙個可以匹配的地方,我們標記一次,最後對於每乙個模式串都從後往前跑一遍,當我們發現乙個地方被標記後,就輸出答案(從後往前跑所找到的第乙個一定是最長的能匹配的字首)

還有就是這道題的資料範圍很迷,陣列一定要開夠

下面給出**:

#include#include

#include

#include

#include

#include

#include

using

namespace

std;

inline

intrd()

inline

void write(int

x)int

n,m;

char s[10000006],a[106

];int trie[1000006][4

];int len[100006],f[10000006

];int vis[10000006

];int tot=1

;int calc(char

ch)void pre(int

x) c=trie[c][h];

}vis[x]=c;

return;}

int q[1000006

];int l=0,r=0

;int nxt[1000006

];void

get_next()}}

return;}

bool book[1000006

];void

solve()

}return;}

int gets(int

x)int

main()

get_next();

solve();

for(int i=1;i<=m;i++) printf("

%d\n

",gets(i));

return0;

}

BZOJ 4327 JSOI2012 玄武密碼

字尾自動機裸題。藉著這道裸題總結一下字尾自動機的查詢問題。1.查字首 查詢時不跳parent,遇到空節點就跳出。2.查子串 查詢時跳parent,記錄最大ans.3.查次數 lct維護right陣列 4.查不同的串的數目 在建樹時維護,乙個點對答案的貢獻為this max len this pare...

BZOJ4327 JSOI2012玄武密碼

description 在美麗的玄武湖畔,雞鳴寺邊,雞籠山前,有一塊富饒而秀美的土地,人們喚作進香河。相傳一日,一縷紫氣從天而至,只一瞬間便消失在了進香河中。老人們說,這是玄武神靈將天書藏匿在此。很多年後,人們終於在進香河地區發現了帶有玄武密碼的文字。更加神奇的是,這份帶有玄武密碼的文字,與玄武湖南...

BZOJ4327 JSOI2012 玄武密碼

對所有詢問串建立ac自動機。然後將母串在ac自動機上跑,每走到乙個點x,從x點出發沿著fail指標能到的所有字首都是匹配成功的,暴力向上走,碰到走過的就break,這樣每個點最多隻會被標記一次。時間複雜度 o n 100m include includeconst int n 10000003,m ...