yzoj1985 最長公共單調上公升子串行 題解

2022-05-06 21:42:10 字數 1739 閱讀 8009

先來說說最長公共子串行,這是一道比較經典的dp題,我們可以很容易寫出

1.狀態f[i][j]表示a序列匹配到第i個b序列匹配到第j個的最長長度

2.狀態轉移方程

f[i][j] = max(f[i-1][j] , f[i][j-1]) (a[i] != b[j])

f[i][j] = f[i-1][j-1]+1(a[i] = b[j])

答案就在f[n][m]中

**

#includeusing namespace std;

int n,m,f[5010][5010];

char a[5010],b[5010];

int main()

}printf("%d",f[n][m]);

return 0;

}

然後我們再來考慮最長公共上公升子串行

1.定義狀態:f[x][y]表示a串匹配長度x,b串匹配長度y,且以b[j]結尾的序列長度。

2.狀態轉移方程:

f[i][j]=f[i][j] = f[i-1][j] (a[i] != b[j])

f[i][j] = max(f[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k])

對於第乙個方程我們可以理解為當a[i]!=a[j]時我們用b序列去匹配a序列匹配失敗了則a[i]這個數是對這個序列沒有貢獻的,即考慮不考慮都無所謂

對於第二個方程我們可以理解為當b序列中第j個數匹配了,我們可以選擇前面所有的狀態進行轉移,但是保證 b[j] > b[k]

#includeusing namespace std;

int n,m,ans,a[3010],b[3010],f[3010][3010];

int main()

f[i][j]=maxn+1;

} } }

for(int i=1;i<=m;++i) ans=max(ans,f[n][i]);

printf("%d",ans);

return 0;

}

但是這樣的做法在最壞情況下可能到達o(n^3),我們可以考慮優化,我們可以發現在第三重迴圈找最大值時是否可以進行一定優化?我們可以發現當有乙個序列a[i]=b[j]時看第二個轉移方程b[j] > b[k]也就是說a[i]>b[k],我們可以利用乙個最大值maxn來存下每次的最大值,即當a[i]>b[j]時更新它,當a[i]=b[j]時f[i][j]=maxn+1;

#includeusing namespace std;

int n,m,ans,a[3010],b[3010],f[3010][3010];

int main()

} for(int i=1;i<=m;++i) ans=max(ans,f[n][i]);

printf("%d",ans);

return 0;

}

我們依然可以發現f[i][j]轉移只用到了f[i][j-1]的數,我們可以再進行優化!利用滾動陣列優化我們的空間。

#includeusing namespace std;

int n,m,ans,a[3010],b[3010],f[3010];

int main()

} for(int i=1;i<=m;++i) ans=max(ans,f[i]);

printf("%d",ans);

return 0;

}

完結撒花!!

最長公共子串行 最長上公升子串行 最長公共上公升子串行

核心 for int i 1 ifor int j 1 jif a i b j else hdu5248 樹狀陣列優化 nl ogn nlo gn include using namespace std const int maxn 100005 char a maxn int len int bi...

最長上公升子串行 最長公共上公升子串行

求最長公共子串行有幾種方法 include include using namespace std include include const int inf 0x3f3f3f3f const int maxn 10005 int a maxn ints maxn int dp maxn int d...

最長公共上公升子串行

題目描述 給定兩個整數序列,求它們的最長上公升公共子串行。輸入描述 輸入兩組資料,每組資料代表乙個整數序列,其輸入格式為 第一行輸入長度m 1 m 500 第二行輸入該序列的m個整數ai 231 ai 231 輸出描述 輸出共兩行。第一行輸出兩個序列的最長上公升公共子串行的長度l 第二行輸出該子串行...