最长公共子序列(LCS)

最长公共子序列(LCS) 

  • dp[i][j] = x表示第一个字符串前i个位置和第二个字符串前j个位置的最长公共子序列长度为x
  •  if(s1[i]==s2[j])  dp[i][j]= dp[i-1][j-1]+1;
  •  else dp[i][j] = max(dp[i-1][j],dp[i][j-1])

POJ1458(裸题)

代码:很好理解。因为字符串从0开始,所以我i和j都分别加1记录。

#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int const N = 1000 + 10;
int dp[N][N];   //dp[i][j]表示第一个字符串前i个位置和第二个字符串前j个位置的最长公共子序列长度为x
string s1,s2;
int main(){
	while(cin>>s1>>s2){
		memset(dp,0,sizeof(dp));
		for(int i=0;i<s1.length();i++)
			for(int j=0;j<s2.length();j++)
				if(s1[i] == s2[j])	dp[i+1][j+1] = dp[i][j] + 1;  //如果相同,那么
				else	dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]);
		printf("%d\n",dp[s1.length()][s2.length()]);
	}
}

UVA11584

题解:

  • dp[i]表示0到i回问串的个数
  • p[i][j]表示i到j是否为回文串
  • 所以dp[i] = min(dp[i],dp[j-1] + p[j][i] == true ? 1 : 0)
#include <bits/stdc++.h>
using namespace std;
int const N = 1000 + 10;
int const inf = 0x7f7f7f7f;
char s[N];
int n,dp[N],p[N][N];
bool ok(char *s,int i,int j){
	while(i < j){
		if(s[i] != s[j])	return false;
		++i,--j;
	}
	return true;
}
int solve(char *s){
	int len = strlen(s);
	dp[0] = 1;
	for(int i=1;i<len;i++){
		dp[i] = dp[i-1] + 1;
		for(int j=0;j<i;j++)
			if(ok(s,j,i))	dp[i] = min(dp[i],dp[j-1]+1);
	}
	return dp[len-1];
}
int main(){
	scanf("%d",&n);
	while(n--){
		scanf(" %s",s);
		printf("%d\n",solve(s));
	}
	return 0;
}

 

posted @ 2019-02-22 17:21  月光下の魔术师  阅读(9)  评论(0)    收藏  举报