您的位置:首页 > 其它

最大子序列、最长递增公共子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

2014-09-13 21:11 375 查看
http://www.cnblogs.com/zhangchaoyang/articles/2012070.html

最大子序列

最大子序列是要找出由数组成的一维数组中和最大的连续子序列。比如{5,-3,4,2}的最大子序列就是 {5,-3,4,2},它的和是8,达到最大;而 {5,-6,4,2}的最大子序列是{4,2},它的和是6。你已经看出来了,找最大子序列的方法很简单,只要前i项的和还没有小于0那么子序列就一直向后扩展,否则丢弃之前的子序列开始新的子序列,同时我们要记下各个子序列的和,最后找到和最大的子序列。

http://acm.hdu.edu.cn/showproblem.php?pid=1003

//模板,思想。
#include<stdio.h>
#define Min -999999
int main()
{
int data[100000],start,end,t,i;
int m;
scanf("%d",&m);
for(t=1;t<=m;t++)
{
int n;
scanf("%d",&n);
for ( i=1; i<=n;i++)
scanf("%d",&data[i]);
int max = Min;
int k=1;
int sum = 0;
for (i=1; i<=n; i++)
{
sum = sum + data[i];
//printf("sum=%d\n",sum);
if (sum > max)
{
//  printf("max=%d\n",max);
max = sum;
start=k;
end=i;
}
if(sum<0)
{
sum=0;
k=i+1;
}
}
printf("Case %d:\n",t);
printf("%d %d %d\n",max,start,end);
if(t!=m)
printf("\n");
}
return 0;
}


最长公共递增序列

http://acm.hdu.edu.cn/showproblem.php?pid=1423

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[600],b[600];
int GCIS(int l1, int l2)
{
int DP[600];
int i,j,k,max;
memset(DP,0,sizeof(DP));
for (i=1; i<=l1; i++)
{
k=0;
for (j=1; j<=l2; j++)
{
if (b[j-1]<a[i-1] && DP[j]>DP[k])
k=j;
if (b[j-1]==a[i-1] && DP[k]+1>DP[j])
DP[j]=DP[k]+1;
}
}
for(max=0,i=1; i<=l2; i++)
if (DP[i]>DP[max]) max=i;
return DP[max];
}
int main()
{
int T,n,m,i;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0; i<n; i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(i=0; i<m; i++)
scanf("%d",&b[i]);
printf("%d\n",GCIS(n,m));
if(T) printf("\n");
}
return 0;
}


最长公共递增序列记录路径:zoj

/article/1819446.html

最长公共子序列、子序列问题。

http://acm.hdu.edu.cn/showproblem.php?pid=1159

若str1[i]=str2[j] dp[i][j]=dp[i-1][j-1]+1
若str1[i]!=str2[j] dp[i][j]=max(dp[i-1][j],dp[i][j-1])

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char str1[1005],str2[1005];
int dp[1005][1005];
int main()
{
int i,j;
while(~scanf("%s%s",str1,str2))
{
memset(dp,0,sizeof(dp));
int l1=strlen(str1);
int l2=strlen(str2);
if(str1[0]==str2[0])
dp[0][0]=1;
else
dp[0][0]=0;
for(i=1;i<l1;i++)
{
if(str1[i]==str2[0])
dp[i][0]=1;
else
dp[i][0]=dp[i-1][0];

}
for(i=1;i<l2;i++)
{
if(str1[0]==str2[i])
dp[0][i]=1;
else
dp[0][i]=dp[0][i-1];
}

for(i=1;i<l1;i++)
{
for(j=1;j<l2;j++)
{
if(str1[i]==str2[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
//printf("dp=%d\n",dp[i][j]);
}
}
printf("%d\n",dp[l1-1][l2-1]);
}
return 0;
}


最长递增子序列:
http://poj.org/problem?id=2533
这是我觉得简单一点的模板。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int a[10000];
int los(int l)
{
int dp[10000];
int i,j,k,max;
memset(dp,0,sizeof(dp));
for(i=1;i<l;i++)
for(j=0;j<i;j++)
if(a[j]<a[i]&&dp[i]<=dp[j])
dp[i]=dp[j]+1;
for(max=0,i=1; i<=l; i++)
if (dp[i]>dp[max])
max=i;
return dp[max];
}


  但是我自己做的:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int a[10000];
int los(int l)
{
int dp[10000];
int i,j,k,max;
memset(dp,0,sizeof(dp));
for(i=1;i<=l;i++)
{
k=0;
for(j=1;j<=i;j++)
{
if(i==j)
continue;
if(a[i-1]>a[j-1])
k=j;
if(dp[k]+1>dp[i]&&k!=0)
dp[i]=dp[k]+1;
}
}
for(max=0,i=1; i<=l; i++)
if (dp[i]>dp[max])
max=i;
return dp[max];
}
int main()
{
int i,n;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("%d\n",los(n)+1);
}
return 0;
}


但是有时最长递增子序列的时间缩短。
http://poj.org/problem?id=3903
题意:依旧是一道LIS的裸题
思路:要注意数据比较多,要用二分的优化法,原本是与POJ2533一样的题,但是用2533的代码只改下数组大小是过不了的,WA了几次,后来发现二分函数需要改进,于是改成了下面的方式,而且这个二分函数用在2533也是可以的

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int a[100005],c[100005];
int n;
int find(int size,int k)
{
int l,r,mid;
l=1;r=size;
while(l<=r)
{
mid=(l+r)/2;
if(k>c[mid])
l=mid+1;
else
r=mid-1;
}
return l;
}
int LIS()
{
int i;
int cnt=1;
c[++cnt]=a[1];
for(i=2;i<=n;i++)
{
if(a[i]>c[cnt])
c[++cnt]=a[i];
else
{
int k=find(cnt,a[i]);
c[k]=a[i];
}
}
return cnt-1;
}
int main()
{
int i;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d\n",LIS());
}
}


接下来就是这个网站:

http://www.cnblogs.com/zhangchaoyang/articles/2012070.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐