題目背景
djl為了避免成為乙隻鹹魚,來找johann學習怎麼求最長公共子串行。
題目描述
經過長時間的摸索和練習,djl終於學會了怎麼求lcs。johann感覺djl孺子可教,就給他布置了乙個課後作業:
給定兩個長度分別為n和m的序列,序列中的每個元素都是正整數。保證每個序列中的各個元素互不相同。求這兩個序列的最長公共子串行的長度。
djl最討厭重複勞動,所以不想做那些做過的題。於是他找你來幫他做作業。
輸入輸出格式
輸入格式:
第一行兩個整數n和m,表示兩個數列的長度。
第二行一行n個整數a_1,a_2,…,a_n,保證1≤a_i≤〖10〗^9。
第三行一行m個整數b_1,b_2,…,b_m,保證1≤b_i≤〖10〗^9。
輸出格式:
一行乙個整數,表示兩個數列的最長公共子串行的長度。
輸入輸出樣例
輸入樣例#1:
6 6
1 3 5 7 9 8
3 4 5 6 7 8
輸出樣例#1:
4 說明
對於40%的資料,n, m≤3000
對於100%的資料,n, m≤300000
【題解】
為什麼前面的神牛都用了stl函式upper——bound,我這個小蒟蒻不懂。。。
於是乎,我寫了個沒用這個stl函式的**,速度慢到爆(最後乙個點0.9s+)。
此題難點是
1、資料範圍過大,這需要用不定長陣列map(不懂看度娘)
2、此題資料是用來卡ac的,所以要先將其轉化為乙個子串行(map的對映功能),再用優化演算法——lis的n*logn演算法。
3、lis的n*logn演算法:d[i]保留滿足f[i] = k的所有a[i]中的最小值。f[i]表示從1到i這一段中以i結尾的最長上公升子串行的長度。設當前已經求出的最長上公升子串行長度為len。先判斷a[i](乙個子串行)與d[len],若a[i] > d[len],則將a[i]接在d[len]後將得到乙個更長的上公升子串行,len = len + 1,d[len+1] = a[i];否則,在d[1]..d[len]中,找到最大的j,滿足d[j] < a[i].令k = j + 1,則有d[j] < a[i] <= d[k],將a[i]接在d[j]後將得到乙個更長的上公升子串行,同時更新d[k] = a[i].最後,len即為所要求的最長上公升子串行的長度。
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
mapf;//不定長陣列,相當於一種對映,具體請問度娘
int a[300009]={},n,m,c[400009]={},d[260000]={},aa,bb;
int lcs()
d[l]=c[i];
if(l>t)//如果發現找出的位置在最後面,那就加長度
t++;
}return t;
}int main()
int ans=lcs();//lis的n*logn演算法
cout
0;}
P3402 最長公共子串行
p3402 最長公共子串行 經典問題 lcs lis 沒有重複的值才可以這麼做 把第一數列轉化成1 n,然後將第二個數列對映成1 n中的一些數,然後求第二個數列的lis即可,然後用bit求lis,o nlogn 資料太大,考慮map include include include include i...
P3402 最長公共子串行(nlogn)
先看一下資料規模 n 300000,n 2的做法肯定就要掛掉了,所以用到了這個nlogn的做法。先介紹一下nlogn的做法 最長公共子串行 的 nlogn 的演算法本質是 將該問題轉化成 最長增序列 lis 因為 lis 可以用nlogn實現,所以求lcs的時間複雜度降低為 nlogn。轉化 將lc...
洛谷 P1439 最長公共子串行
傳送門 給出1 n的兩個排列p1和p2,求它們的最長公共子串行。輸入格式 第一行是乙個數n,接下來兩行,每行為n個數,為自然數1 n的乙個排列。輸出格式 乙個數,即最長公共子串行的長度 輸入樣例 5 3 2 1 4 5 1 2 3 4 5 輸出樣例 3 資料規模 對於50 的資料,n 1000 對於...