SSLOJ2666勇闯黄金十二宫射手宫andSSLOJ1463最长公共子序列模板

Description

第九个他们来到射手宫,身为射手座黄金圣斗士的艾尔里斯是狮子座圣斗士艾尔里亚的哥哥,他早在13年前就发现了撒加杀了真教皇,并且自己做了假教皇。然而他却被撒加迫害致死。现在星矢四人已经来到了射手宫。艾尔里斯的灵魂想考验一下这些圣斗士们的水平,在射手宫的墙上留下了一道题目。 “已知艾尔里斯和弟弟艾尔里亚的基因基本相同,由于基因表达起来不方便,所以就用n个数字来表示。(因为至今共发现100000种基因,所以每个数字都<=100000)兄弟之间的基因个数是相同的,就是说他们都有n个数字。且对于每个人,这n个数字互不相同。现在要求兄弟之间基因的最长公共部分。可以不连续。” 如果,他们解决不了这题,就通不过射手宫了。不过还好,他们顺利地通过了!

Input

本题包含多组数据. 第1行,为n(1<=n<=100000) 下面2行,每行n个数字,表示了一个人的所以基因。

Output

对于每组数据输出一行,为他们两人基因的最长公共部分。

Sample Input

7
1 2 3 4 5 6 7
7 6 5 4 1 2 3

Sample Output

3

思路

这是最长公共子序列的板子题,但是由于数据太大,不可以用普通解法,于是先求出相同的基因的编号存在u中,然后用最长不上升子序列计算个数(要单调队列优化)优化方法:

  1. 设一个数组d为最长上升子序列,把d[1]置为u[1],并设置长度len为1
  2. 对于每一个u[i](2<=i<=n),如果它>d[len](即目前的最优序列中没有可以替换的值),d[++len]=u[i]
  3. 否则2分查找出第一个可以替换的值(第一个>u[i]的位置)并替换
  4. 输出len,AC
#include
#include
#include
#include
using namespace std;
map<int,int> f;
int d[100001],len,a,b,u[100001],l;
int main()
{
	int n;
	cin>>n;
	for (int i=1;i<=n;i++) scanf("%d",&a),f[a]=i;
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&b);
		if (f[b]!=0) u[++l]=f[b];
	}
	d[1]=u[1];
	len=1;
	for (int i=2;i<=n;i++)
	{
		if (u[i]>d[len]) d[++len]=u[i];
		else
		{
			int j=upper_bound(d+1,d+1+len,u[i])-d;//求d数组中第一个>u[i]的位置,头文件algorithm
			d[j]=u[i];
		}
	}
	cout<<len;
	return 0;
}

Description

设有A、B两个字符串,找出A、B共同子串,每个字符串无相同字符,可以不连续,但顺序不能颠倒。

Input

第一行字符串A

第二行字符串B

Output

最长公共子串的长度.

Sample Input

abcfbc
abfcab

Sample Output

4

思路

这题就是上面的简化版,可以写模板:
设f[i][j]为第一个字符串的前i个字符和第2个的前j个字符的最长公共子序列的长;
公式:
若 第 一 个 串 的 第 i 个 与 第 二 个 串 的 第 j 个 相 等 : f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] + 1 若第一个串的第i个与第二个串的第j个相等:f[i][j]=f[i-1][j-1]+1 ijf[i][j]=f[i1][j1]+1
否 则 : f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ) 否则:f[i][j]=max(f[i-1][j],f[i][j-1) f[i][j]=max(f[i1][j],f[i][j1)
1<=i<=n,1<=j<=m
上代码:

#include<iostream>
#include<cstdio>
using namespace std;
int f[1004][1004];
int main()
{
	string a,b;
	cin>>a>>b;
	int n=a.size(),m=b.size();
	a=' '+a;
	b=' '+b;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		{
			f[i][j]=max(f[i-1][j],f[i][j-1]);
			if (a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1); //其实没有必要比较f[i-1][j]、f[i][j-1]和f[i-1][j-1]+1的,f[i-1][j-1]+1一定更大
		}
	}
	cout<<f[n][m]; 
    return 0;
}

你可能感兴趣的:(dp)