題目:最長公共子串行
思路:這題用一般的dp來做,f( i , j )表示a的前i位和b的前j位的最長公共子串行的長度,時間複雜度為o(n^2),在這題會tle。
在這題中,需要用o(nlogn)的複雜度實現。
先設計乙個陣列b,b[i]代表b串中的數第i個數在a串中的位置。例如:
a串: 3 2 1 4 5
b串: 5 4 3 2 1
b[ ]: 5 4 1 2 3
這時,求ab兩串的最長公共子串行也就是求b的最長上公升子串行。因為乙個序列x是ab的共共子串行,當且僅當x中的每乙個數對應在ab兩串的位置,都小於下乙個數在ab兩串中對應的位置。也就是說,x的每乙個數在ab兩串中對應的位置都是遞增的。
b陣列的設定就是相當於把a排了序,使a中的數遞增,那麼要是b中的數遞增,就需要求b的上公升子串行。
求最長上公升子串行的樸素的dp做法的複雜度也是o(n^2),但是可以用二分優化成o(nlogn)。
令f[x]表示b中最長上公升子串行為x時序列的最後乙個數的最小值。可以利用貪心的思想得到,每遍歷到乙個數b[i]時,f[x]=min(b[i],f[x]),其中x等於取乙個最大的j使得f[j]的值小於b[i]的f[j]的值。由於f的值一定是有序的,所以求這個值就可以二分了。
注意這裡的二分寫的是stl庫中的 lower_bound 函式。
**:
#includeusing namespace std;
#define maxn 100000
int n;
int a[maxn+5]=,b[maxn+5]=;
int f[maxn+5]=;
int main()
for(int i=1;i<=n;i++)
for(int i=2;i<=n;i++) f[i]=(1<<30);
f[1]=b[1],f[0]=0;
int len=1;
for(int i=2;i<=n;i++)
int x=lower_bound(f+1,f+len+1,b[i])-f;
f[x]=min(b[i],f[x]);
} printf("%d",len);
return 0;
}
洛谷 1439 最長公共子串行
題目描述 給出1 n的兩個排列p1和p2,求它們的最長公共子串行。輸入格式 第一行是乙個數n,接下來兩行,每行為n個數,為自然數1 n的乙個排列。輸出格式 乙個數,即最長公共子串行的長度 輸入輸出樣例 輸入 1 53 2 1 4 5 1 2 3 4 5 輸出 1 3說明 提示 資料規模 對於50 的...
洛谷 P1439 模板 最長公共子串行
lis lcs 對映 題目描述 給出1 n的兩個排列p1和p2,求它們的最長公共子串行。輸入輸出格式 輸入格式 第一行是乙個數n,接下來兩行,每行為n個數,為自然數1 n的乙個排列。輸出格式 乙個數,即最長公共子串行的長度 輸入輸出樣例 輸入樣例 1 5 3 2 1 4 5 1 2 3 4 5 輸出...
洛谷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 對於1...