同步
原題鏈結
簡要題意:
給定兩個 1
11 ~ n
nn 的排列,求其最長公共子串行。
嗯,下面給出若干演算法吧。
不管它是 1
11 ~ n
nn 的排列這一性質。
求 lcs
\text
lcs(即最長公共子串行)的套路方法:
用 f i,
jf_
fi,j
表示 a
1a_1
a1 ~ a
ia_i
ai 和 b
1b_1
b1 ~ b
jb_j
bj 的最長公共子串行。那麼不考慮邊界問題,則存在:
f i,
j=
= \begin f_+ 1 , a_i = b_j \\ \max(f_ , f_) \end
fi,j=
lcs 的求法,然後發現最優的 dp
\text
dp 就是 o(n
2)
o(n^2)
o(n2)?
但是注意到乙個性質 ,兩個陣列都是 1
11 ~ n
nn 的排列。
所以今天我們要秀出什麼操作呢!
5
3 2 1 4 5
1 2 3 4 5
嗯,如果我們把3 2 1 4 5
變成1 2 3 4 5
,即建立一種關係為:
3 - 1
2 - 2
1 - 3
4 - 4
5 - 5
然後1 2 3 4 5
它就變成了3 2 1 4 5
(這純屬巧合啊)。
你發現,通過這樣一波操作,其實 lcs
\text
lcs 本質就是在 b
ib_i
bi 中找到若干個在 a
ia_i
ai 中有序出現的子串行。
顯然一波操作之後 a
ia_i
ai 有序,然後就是直接求 b
ib_i
bi 的 lis
\text
lis(最長上公升子串行)即可。因為任意的兩個 x
<
yx < y
x<
y 顯然對應的 a
ia_i
ai 也滿足有該序列。
時間複雜度:o(n
logn)
o(n \log n)
o(nlogn)
.實際得分:100pt
s100pts
100pts
.
#pragma gcc optimize(2)
#include
using
namespace std;
const
int n=
1e5+1;
inline
intread()
int x=0;
while
(ch>=
'0'&& ch<=
'9') x=
(x<<3)
+(x<<1)
+ch-
'0',ch=
getchar()
;return x*f;
}int a2[n]
,a1[n]
,be[n]
;int b[n]
,f[n]
,ans,n;
intmain()
int t=
lower_bound
(b+1
,b+1
+ans,be[a2[i]])
-b; b[t]
=be[a2[i]
]; f[i]
=t;}
printf
("%d\n"
,ans)
;return0;
}
P1439 模板 最長公共子串行
給出1 n的兩個排列p1和p2,求它們的最長公共子串行。第一行是乙個數n,接下來兩行,每行為n個數,為自然數1 n的乙個排列。乙個數,即最長公共子串行的長度 輸入 1複製 5 3 2 1 4 5 1 2 3 4 5輸出 1複製 3 資料規模 對於50 的資料,n 1000 對於100 的資料,n 1...
P1439 模板 最長公共子串行
p1439 模板 最長公共子串行 這個題目我是沒想到反正我感覺十分的神奇先寫一下我在洛谷題解區看見的乙個很好理解的題解 對於樣例 3 2 1 4 5 1 2 3 4 5 我們可以把第乙個陣列編號位a b c d e 那麼第二個陣列就變成了c b a d e 現在對於第二個陣列的最長上公升子串行就是答...
P1439 模板 最長公共子串行
給出1 n的兩個排列p1和p2,求它們的最長公共子串行。輸入格式 第一行是乙個數n,接下來兩行,每行為n個數,為自然數1 n的乙個排列。輸出格式 乙個數,即最長公共子串行的長度 輸入樣例 1 複製 5 3 2 1 4 5 1 2 3 4 5 輸出樣例 1 複製 3 資料規模 對於50 的資料,n 1...