沒有傳送門。
給定乙個長為 \(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 否則,我們定義這個單詞沒有正確使用大寫字...