參考資料比如 \(\texttt\) 就是乙個 \(\text\)。而 \(\texttt\) 則不是,因為 \(\texttt<\texttt\)。
根據定義顯然得證。
證明:令 \(w=u+v\)。
任取 \(v\) 的乙個字尾 \(v'=v[i:]\),若 \(|v'|\leq |u|\) 或 \(u<^v\),則有 \(u<^v'\),故 \(w。
否則有 \(u=v[1:|u|]\)。假設有 \(w>v\),對於 \(l=|v|-|u|\),有 \(v[:l]\geq v[n-l+1:]\),與性質 2 不符。
故 \(w\) 小於 \(v\) 中的任何乙個字尾。
再任取 \(u\) 的乙個字尾 \(u'=u[i:]\),由於 \(u>^u'\),故 \(w>u'+v\)。
至此我們證明了 \(w\) 是乙個 \(\text\) 。
形式化說,構造乙個序列 \(t_i\),使 \(t_1+t_2+\cdots+t_n=s\),且 \(\forall i\ ,\ t_i\) 是乙個 \(\text\)。
通常 \(\text\) 分解採用 duval 演算法。
考慮將字元依次加入,維護當前的 \(\text\) 分解:
我們假設分解形式為 \(t+t'^k+t'[:p]\),其中 \(t=t_1+t_2+\cdots+t_\)。保證有 \(t_1\geq t_2\geq \cdots \geq t_>t'\)。
考慮我們加入乙個字元 \(c\),設 \(v\) 表示 \(t'[:p\bmod |t'|+1]\),如果:
\(c=v\) :轉移到分解 \(t+t'^k+t'[:p+1]\)(如果 \(p=|t'|\) 則是 \(t+t'^\))。
\(c:令 \(j\in[1,k],s_=t'\),轉移到 \(t'+(t'[:p]+c)\)。
\(c>v\ ,\ t'^k+t'[:p]+c\) 是乙個 \(\text\) :令 \(s_=t'^k+t'[:p]+c\),轉移到 \(t'\)。,複雜度 \(o(n)\)。
考慮到 \(t'^k+t'[:p]\) 本質是乙個迴圈串,故維護三個變數 \((i,j,k)\),其中 \(i\) 是首字母位置,\([j,k]\) 是最後乙個迴圈節的位置。
這樣對於情況一,令 \(i+1,j+1\)。情況二則從 \(i\) 開始每 \(k-j+1\) 劃分乙個分解。情況三則令 \(j=i\)。
#include#include#include#define n 5000010
using namespace std;
char s[n];
int p[n],t;
int main()
t_1\) 分類討論,如果沒有再根據是否有 \(|u|,如果是則遞迴 \(t_2\) 討論,否則可以推出 \(t_1\) 不是乙個 \(\text\)。
從後往前加字元,考慮維護乙個單調棧,設 \(t_0\) 是棧頂,滿足 \(t_i\geq t_\)。對於 \(p\) 位置新加的字元 \(c\),我們令 \(s'=c\)。每次判斷是否有 \(s'。如果有則彈出棧頂,令 \(s_m=s_m+t_0\)。重複上述步驟直到滿足單調性質,此時的 \(s_m\) 的右端點即 \(\lambda_p\)。
使用hash+二分處理兩個串的大小關係可以做到 \(o(n\log n)\) 的複雜度。若使用 sa-is 加 \(o(n)-o(1)\) st表可以做到 \(o(n)\) 的時間複雜度。
即某乙個字串不斷迴圈得到 \(s\)。這裡並不一定要整迴圈,比如 \(3\) 就是 \(\texttt\) 的乙個 \(\text\)。
比如 \(\texttt\) 中:
\((1,8,2)\) 是乙個 \(\text\) 。
\((3,8,2)\) 不是,因為這個這個週期串可以繼續向左延伸。
\((1,8,4)\) 不是,因為 \(p=4\) 不是 \(s[1:8]\) 的最小 \(\text\)。
\((6,10,3)\) 不是,因為 \(p=3\) 沒有出現至少兩次,即 \(p>\frac\)。
這個其實就是上面 \(\text\) 分解所用的結論。
證明:找到 \(\overline[i:]\) 第乙個與 \(\overline_i\) 不同的位置 \(p'\)。即 \(\min\_\neq \overline_p\}\)。令 \(\ell\) 滿足 \(s_<_s_p\),由引理1顯然有 \(l_=[i,i]\),\(l_}\neq[i,i]\)。(此處 wc2019 的課件貌似有誤?課件好像取的是 \(\max\))。
具體證明大概就是根據引理 2 用反證推出如果存在交集,取交集的位置就能推出週期性,與 \(\text\) 的定義不符。
接下來考慮如何快速求的 \(\text(s)\)。
考慮我們先求出 \(l_(i)\),即以 \(i\) 開頭最長的 \(\text\)。容易發現這個就是1.3 \(\textbf\) 陣列。
獲得了所有 \(l_(i)\) 後,我們令 \(p=l_(i)-i+1\),觀察其向左向右能延伸到的最遠的地方 \([l',r']\)。對於三元組 \((l',r',p)\),我們只需要判斷其是否滿足 \(p\leq \frac 2\) 即可。
實現細節:一種比較 \(\text\) 的方式是用 hash+二分處理兩個串的 \(\text/\text\)。對於子串大小比較直接比較 \(\text\) 的後一位即可。判斷延伸到的最遠的位置 \([l',r']\),可以發現對於 \(l'\) 一定有 \(s[l':i]=s[l'+p-1:s+p-1]\),所以直接取 \(s[:i],s[:l_(i)]\) 的 \(\text\) 即可。\(r'\) 同理。這樣總複雜度是 \(o(n\log n)\)。
上述複雜度瓶頸在於求 \(\text\)。用 sa-is 套 \(o(n)-o(1)\) st表可以優化到 \(o(n)\)。
至此就完成了 \(\text\) 的求解。
#include#include#include#include#include#define n 1000010
#define ull unsigned long long
#define b 2333
using namespace std;
char str[n];
int s[n],n;
ull h[n],bs[n];
ull get(int l,int r)
int lcp(int x,int y)
return res;
}int lcs(int x,int y)
return res;
}bool cmp(int l1,int r1,int l2,int r2)//s[l1:r1]min(r1-l1,r2-l2)) return r1-l1ans;
int st[n],t,run[n];
void lyndon()
}void init()
void get_runs()
}int main()
學做事,先學做人
經理很關照我,我很感謝經理。其實,有乙個好的領導,只要好好幹,他是一定會知道的。但是,要改變客戶的看法,看來還真的很難。在客戶面前不可以太謙虛,太過謙虛,他們反覺得我們無能。做事先做人,一點都沒錯啊。感覺自己太嫩了,這一切還得慢慢磨練。希望多看數,多學習,多仔細觀察生活,觀察周圍成功的人,不斷提高自...
B 學密碼學真的得學程式
b 學密碼學真的得學程式 time limit 1000msmemory limit 65536kb64bit io format lld llu submit status practice sdutoj 2464 description 話說,上次zyj同學最終在眾位瑪麗亞的幫助下搞定了那個神奇...
學密碼學一定得學程式
time limit 1000ms memory limit 65536k 曾經,zyj同學非常喜歡密碼學。有一天,他發現了乙個很長很長的字串s1。他很好奇那代表著什麼,於是神奇的wl給了他另乙個字串s2。但是很不幸的是,wl忘記跟他說是什麼意思了。這個時候,zyj不得不求助與偉大的zp。zp笑了笑...