題解 字母 letter

2022-02-14 07:50:14 字數 2887 閱讀 9580

沒有傳送門。

給定乙個長為 \(n\) 字串 \(\text\),現取出 \(\text\) 的所有子串,並按字典序從小到大排序,然後將這些排好序的字串首尾相接,記為字串 \(\text\)。共有 \(\text\) 次詢問,每次詢問 \(\text\) 中的第 \(\text\) 個字元。

【輸入格式】

第一行輸入乙個字串 \(\text\),第二行乙個正整數 \(\text\) 。

接下來 \(\text\) 行,每行兩個正整數 \(\text\) 。

【輸出格式】

對於每次詢問,輸出一行乙個字元表示答案。

【輸入輸出樣例】

樣例輸入:

caaacacbbbababba

63 101

16 101

21 41

22 129

33 131

40 100

樣例輸出:aa

abca

【資料範圍】

\(100\%:\)

\(1 \leqslant \text \leqslant |\text|, 1 \leqslant \text \leqslant 10^9\),\(\text\) 中僅包含小寫字母。

測試點字串 \(\text\) 的長度 \(n\)

詢問的次數 \(\text\)

\(1\)

\(1 \leqslant n \leqslant 50\)

\(1 \leqslant \text \leqslant 200000\)

\(2,3\)

\(1 \leqslant n \leqslant 2000\)

\(1 \leqslant \text \leqslant 20000\)

\(4,5\)

\(1 \leqslant n \leqslant 200000\)

\(1 \leqslant \text \leqslant 10\)

\(6,10\)

\(1 \leqslant n \leqslant 200000\)

\(1 \leqslant \text \leqslant 200000\)

鬼畜題見多了後遇到這種碼農題感覺開心的要死。

看到有「所有子串」這樣的字樣,基本上就是三種字尾演算法實錘了,\(std\) 給的是字尾陣列的做法,但個人認為這道題用字尾樹要簡單一些。

首先是對所有的子串進行排序,明顯為字尾樹的板子操作。用 \(\text\) 構造好 \(\text\) 樹,順序遍歷得到的節點序列 \(id\) 即可滿足字典序從小到大,且對於同一節點中儲存的子串,其長度越小字典序就越小。

在建 \(\text\) 的時候記錄下 \(maxlen,siz\)

\((|\|)\) 和 \(pos\)

\((\\) 中的任意乙個 \()\),則 \(\text\) 中的乙個儲存資訊的節點 \(x\) 所囊括的子串有:某乙個字首 \(prefix\) 的 \(len\) 個字尾,長度分別為 \(minlen(x),minlen(x)+1...maxlen(x)\),其中 \(len=maxlen(x)-minlen(x)+1\)。所以 \(x\) 中所囊括的字元個數為:\(cnt[x]=siz[x]\sum_^i\) 。

設 \(s[n]=\sum_^cnt[id[i]]\),每次查詢在 \(s\) 中二分找到答案所在的節點\(x\),然後在 \([minlen(x),maxlen(x)]\) 中二分找到答案所在的子串長度,最後用 \(\text\) 對該子串長度取模即可得到答案的位置(取模是因為該子串可能會出現多次)。

字尾演算法的細節考慮通常都很複雜,這道題也不例外,思維難度不高,但實現起來非常麻煩,考試時碼了乙個小時 \(\text\),然後又 \(\text\) 半小時,算上寫暴力和對拍的時間,前前後後花了接近三個小時。。。

時間複雜度為:\(o(n+qlogn)\),實測比字尾陣列的 \(o((n+q)logn)\) 快了好幾倍。

#include#include#include#define ll long long

#define re register int

using namespace std;

const int n=4e5+10;

int n,x,y,t;ll p,m,g,k;char s[n>>1];

inline void in(re &x)

struct sakura2

}last=z;

}int t,id[n],to[n][26];ll s[n];

//to[x][ch]: 字尾樹的trans陣列

//id[x]: 順序遍歷字尾樹的第x個節點編號

//s[x]: 順序遍歷字尾樹的前x個節點總共代表了多少個字元

inline void dfs1(re x)

inline void dfs2(re x)

inline ll calc(re l,re r)//計算從l加到r的等差數列

inline void build()

inline char ask(ll k)

k-=1ll*siz[x]*calc(maxlen[link[x]]+1,l-1),k=(k-1)%l+1;//注意取模的方式

return s[pos[x]-k+1];//注意方向:往左數第k位

}char ans;

inline void sakura()

}t2;

int main()

Python程式設計PTA題解 字典合併

description 字典合併。輸入用字串表示兩個字典,輸出合併後的字典,字典的鍵用乙個字母或數字表示。注意 1和 1 是不同的關鍵字!input 輸入僅一行,輸入在第一行中輸入第乙個字典字串 在第二行中輸入第二個字典字串 output 在一行中輸出合併的字典,輸出按字典序。1 的ascii嗎為4...

LeetCode題解 字串轉整數 atoi

我的leetcode 集 題目描述 知識點 字串 對於這一題來說,難點不在演算法的實現上,難點在理解題意並正確處理各種邊界或者特殊情況上。1 如果第乙個非空字元是正號或負號,選取該符號,並將其與後面盡可能多的連續的數字組合起來,這部分字元即為整數的值。2 如果第乙個非空字元是數字,則直接將其與之後連...

LeetCode題解 520 檢測大寫字母

瞧一瞧 求star 給定乙個單詞,你需要判斷單詞的大寫使用是否正確。我們定義,在以下情況時,單詞的大寫用法是正確的 全部字母都是大寫,比如 usa 單詞中所有字母都不是大寫,比如 leetcode 如果單詞不只含有乙個字母,只有首字母大寫,比如 google 否則,我們定義這個單詞沒有正確使用大寫字...