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

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

http://blog.csdn.net/cclsoft/article/details/4537299

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

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

posted @ 2014-09-13 21:11  疯狂的癫子  阅读(176)  评论(0编辑  收藏  举报