码迷,mamicode.com
首页 > 其他好文 > 详细

线性DP模板

时间:2020-06-22 20:59:53      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:字符   ret   为我   pre   线性   公共子串   定义   最长公共子序列   复杂   

最长上升子序列

定义

设有由\(n\)个不相同的整数组成的数列,记为: \(b_1,b_2...b_n\)\(b_i!=b_j(i!=j)\)

若存在\(i_1<i_2<...<i_n\)且有\(b_{i_1}<b_{i_2}...<b_{i_3}\)则称为长度为\(e\)的不下降序列。

\(O(n^2)\)的做法

for(int i = 1, m; i <= n; i++) {
	m = 0;
	scanf("%d", &a[i]);
	for(int j = 1; j < i; j++)
		if (a[j] < a[i] && s[j] >m)
			m = s[j];
	s[i] = m + 1;
	if (s[i] > ans) ans = s[i];
}

\(O(n log n)\)的做法

对于\(n^2\)的写法,状态是无法优化的,第二维是求\(j~i\)符合条件的最大子序列和

\(b(i)\)定义为长度为\(i\)的最后一位数

看定义可能不太懂~~因为我就没看懂~~

看着挺复杂,其实也没啥,看代码注释吧

int lis(int a[], int n) {
	int b[N], cnt = 1;
	b[cnt] = a[1];
	for(int i = 2; i <= n; i++) {
		if (a[i] >= b[cnt]) b[++cnt] = a[i];
		//求上升序列,如果a[i]比最后一位大,就在后面再添一个
		else b[upper_bound(b+1, b+cnt+1, a[i])-b] = a[i];
		//找到比他小的替换掉他
		//upper_bound() 用到库<algorithm>
		//也可以手写二分
	}
	return cnt;
}

最长公共子串

定义

一列字符C既是A的子串,又是B的子串,就称C为A和B的公共子串

(这里子串指的是连续的)

\(O(n^2)\)

scanf("%s %s", a+1, b+1);
n = strlen(a+1); m = strlen(b+1);
for(int i = 1; i <= n; i++)
	for(int j = m; j > 0; j--) {
		if (a[i] == b[j])
			s[j] = s[j-1] + 1, ans = max(ans, s[j]);
		else s[j] = 0;
	}

最长公共子序列

定义

一列字符C既是A的子序列,又是B的子序列,就称C为A和B的公共子序列

(这里子序列可以不连续)

\(O(n^2)\)

for(int i = 1; i <= n; i++)
	for(int j = 1; j <= n; j++)
		if (a[i] == b[j]) f[i][j] = f[i-1][j-1] + 1;
		else f[i][j] = max(f[i-1][j], f[i][j-1]);
//f[n][n]为最后的结果

线性DP模板

标签:字符   ret   为我   pre   线性   公共子串   定义   最长公共子序列   复杂   

原文地址:https://www.cnblogs.com/Z8875/p/13178985.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!