《**楊氏矩陣在資訊學競賽中的應用 袁方舟》膜拜有感
前方高能,非戰鬥人員請撤離(都是很幹的數學概念)
楊表 (young tableaux),又叫楊氏矩陣,是乙個啥都能摻一腳的代數結構。
為了方便討論,先來點定義。
楊圖:令 \(\lambda = (\lambda_1,\lambda_2,\ldots,\lambda_m)\) 滿足 \(\lambda_1\ge\lambda_2\ge\ldots\lambda_m\ge 1,n=\sum \lambda_i\)。乙個形狀為 \(\lambda\) 的楊圖是乙個**,第 \(i\) 行有 \(\lambda_i\) 個方格,其座標分別為 \((i,1)(i,2)\ldots(i,\lambda_i)\)。下圖為 \(n=9,\lambda=(4,2,2,1)\) 的楊圖。
\[\left[\begin
* & * & * & * \\
* & * \\
* & * \\
*\end\right]
\]半標準楊表:將楊圖填上數字,滿足每行數字單調不減,每列數字單調遞增。
標準楊表:將 \(1,2,\ldots,n\) 填入楊圖,滿足每行、每列數字單調遞增。下圖為 \(n=9,\lambda=(4,2,2,1)\) 的一種標準楊表。
\[\left[\begin
1 & 4 & 7 & 8 \\
2 & 5 \\
3 & 9 \\
6\end\right]
\]斜楊圖:令 \(\lambda = (\lambda_1,\lambda_2,\ldots,\lambda_m),\mu=(\mu_1,\mu_2,\ldots,\mu_)\),則形狀為 \(\lambda/\mu\) 的斜楊圖為楊圖 \(\lambda\) 中扣去楊圖 \(\mu\) 後剩下的部分。下圖為 \((9, 7, 5, 1)/(5, 3, 2)\) 的斜楊圖。
\[\left[\begin
\cdot & \cdot & \cdot & \cdot & \cdot & * & * & * & * \\
\cdot & \cdot & \cdot & * & * & * & * \\
\cdot & \cdot & * & * & * \\
*\end\right]
\]斜半標準楊表、斜標準楊表:猜都猜得到,不浪費時間了。
rsk 演算法包括了插入和刪除。刪除操作其實就是插入反過來,不影響理解楊表就不寫了。
想要插入 \(x\) 時,從第一行開始,在當前行中找最小的比 \(x\) 大的數字 \(y\) (upperbound)(其實大於 \(x\) 還是大於等於 \(x\) 要看具體情況),交換 \(x,y\),轉到下一行繼續操作;若所有數字比 \(x\) 小則把 \(x\) 放在該行末尾並退出(如果超出了楊圖的行數,那麼楊圖行數加 \(1\))
舉個 \(\alpha\) 粒子,將 \(3\) 插入下圖半標準楊表:
\[\left[\begin
1 & 3 & 3 & 5 \\
2 & 6 \\
4\end\right]
\begin\leftarrow 3\\\\\\\end
\]第一行找到 \(5\),變成:
\[\left[\begin
1 & 3 & 3 & 3 \\
2 & 6 \\
4\end\right]
\begin\\\leftarrow 5\\\\\end
\]第二行找到 \(6\),變成:
\[\left[\begin
1 & 3 & 3 & 3 \\
2 & 5 \\
4\end\right]
\begin\\\\\leftarrow 6\\\end
\]第三行找不到比 \(6\) 大的數字,放到末尾:
\[\left[\begin
1 & 3 & 3 & 3 \\
2 & 5 \\
4 & 6
\end\right]
\]可以證明這樣操作後仍然滿足半標準楊表的定義。
上**!
vectora[n];
void insert(int x)
swap(x, *it);
}}
lis (longest increasing subsequence) 就是廣為人知的最長上公升子串行(有時是不下降)。楊表之所以能和 lis 有關,是因為楊表的插入操作,只看其中一行的話,正好是 dp 求 lis 的演算法。(雖然這是廢話)
拓展一下,如果要求 \(k\) 個不相交的 lis,它們的長度之和最大為楊圖前 \(k\) 行長度之和,即 \(\lambda_1+\lambda_2+\ldots+\lambda_k\)。不過要注意,楊表前 \(k\) 行並不能告訴我們 lis 有哪些數。(類似 dp 求 lis 後那個 dp 陣列也無法告訴我們 lis 有哪些數)
舉個 \(\alpha\) 粒子,如果把 \([1,5,3,2,6,7,4]\) 插入到楊表中得到:
\[\left[\begin
1 & 2 & 4 & 7 \\
3 & 6 \\
5\end\right]
\]顯然 \(1,2,4,7\) 不是 lis,lis 應該是 \(1,5,6,7/1,3,6,7/1,2,6,7\)。不過長度是相同的。
這題就是求 k-lis 的題了。但是 \(k\) 沒有限制,如果維護的楊錶行數太大,樸素的插入演算法 \(o(n^2 \log n)\) 肯定過不了。這就需要乙個楊表的性質:如果把比較運算反過來(大於變小於等於),插入操作後的楊圖和原來的楊圖是轉置關係(但是楊表和楊表不是轉置的,只是形狀轉置),具體可以看看這題的題解。
話說回來,由於楊表和轉置楊表的關係,我們可以得出乙個結論,如果楊表的第一行數字個數是最長上公升子串行長度,那麼第一列數字個數是最長不上公升子串行長度。如果某題限制了最長上公升子串行長為 \(\alpha\),最長不上公升子串行長為 \(\beta\),我們就可以把它和行數為 \(\alpha\),列數為 \(\beta\) 的楊表聯絡起來。(現在還沒用,一一對應的關係在下文會講)
我們可以將排列的數字按順序插入到空楊表中,這樣就會得到乙個標準楊表。但是這會出現兩個排列對應乙個楊表的情況,比如排列 \([2,1,3]\) 和排列 \([2,3,1]\) 都會得到楊表 \(\left[\begin1 & 3 \\ 2 \end\right]\),出大問題。
考慮乙個排列對應兩個楊表,每插入乙個數字到楊表 \(a\),我們在楊表 \(b\) 對應位置記錄這個數字的下標(下標從 \(1\) 開始)。
可以證明 \(b\) 也是個標準楊表。
舉個 \(\alpha\) 粒子,對於排列 \([2,3,1]\),插入 \(2\) 得到:
\[a=\left[\begin2 \end\right],
b=\left[\begin1 \end\right]
\]插入 \(3\) 得到:
\[a=\left[\begin2 & 3 \end\right],
b=\left[\begin1 & 2 \end\right]
\]插入 \(1\) 得到:
\[a=\left[\begin1 & 3 \\ 2 \end\right],
b=\left[\begin1 & 2 \\ 3 \end\right]
\]而 \([2,1,3]\) 會得到:
\[a=\left[\begin1 & 3 \\ 2 \end\right],
b=\left[\begin1 & 3 \\ 2 \end\right]
\]這樣,我們就把乙個排列和兩個標準楊表一一對應了起來。
對合排列是一種特殊的排列,把對合排列當成個置換後,自己乘自己等於單位置換。好理解一點就是a[a[i]]=i
。
比如 \(\left[\begin1 & 2 & 3 \\ 2 & 1 & 3\end\right]\) 就是個對合置換。
為什麼要講對合排列呢,因為把對合排列對應的兩個標準楊表是相等的。這意味著乙個對合置換和乙個楊表是一一對應的關係。
下篇
有一種攻擊叫彩虹表攻擊
在我們日常系統中,很多都有使用者註冊功能,使用者註冊需要使用者名稱和密碼,密碼一般我們都採用md5加密的方式,但是用md5加密,對於乙個固定的字串,其md5值是固定的,這樣就會出現彩虹表攻擊情況。所謂彩虹表攻擊就是指攻擊者有一張表,裡面有密碼明文和對應md5值的對應關係,攻擊者利用這些關係來破解使用...
判斷乙個單向鍊錶上是否有環
判斷乙個單向鍊錶上是否有環的方法有哪些呢?方法1 用乙個指標陣列a,儲存已訪問過的節點。用乙個指標p,每次在鍊錶上移動一步,然後與指標陣列a比較,若陣列中沒有指標與p相同,說明第一次訪問p,將p放入陣列中 若有指標與p相同,則存在環路,且第一次相同的節點就是環的入口點。鍊錶長度為n,則需要空間o n...
mysql表上索引數目有上限
在考慮對redis中的資料建索引時,索引伺服器的實現有兩個備選項 mysql與sqlite。mysql的問題就是乙個表中索引的最大數目是 這樣如果所有的字段都建索引,則乙個表中的字段數不應超過 如果用sqlite做索引服務,可考慮用sqlite的乙個庫表示一張表,庫中的乙個表表示乙個字段。但是表的連...