华为OJ(最长公共子串及公共最长子序列)

先说直观的方法,先给出链接:http://blog.csdn.net/xpyimapingchuan/article/details/46822645

直接上代码,很好懂,不多说了。

方案1:

#include <iostream>
#include <string>
using namespace std;
int main()
{
      string str1,str2;
      getline(cin,str1);
      getline(cin,str2);
      char *s;
      int num=0;
      int max_len=0;
      int start,start1,start2;
      for(int i=0;i<str1.size();i++)
        for(int j=0;j<str2.size();j++)
        {
            start1=i;
            start2=j;
            while(str1[start1] && str2[start2] && str1[start1++]==str2[start2++])
			{
				num++;
				if ((start1)==str1.size() || (start2)==str2.size())
					break;
			}
            if(max_len<num)
            {
                  start=i;
                  max_len=num;
            }
            num=0;
        }
      cout<<max_len<<endl;
     // system("pause");
}
提交后测试用例未全部通过,只有109分,什么鬼?哪里出问题了 不晓得

方案2:使用动态规划,详细讲解在这里:http://blog.csdn.net/hackbuteer1/article/details/6686931

#include<iostream>
using namespace std;
#define N 1000
int getCommonStrLength(char*,char*);
int main()
{
	char pFirstStr[N],pSecondStr[N];
	gets(pFirstStr);
	gets(pSecondStr);
	cout<<getCommonStrLength(pFirstStr,pSecondStr);
	//system("pause");
	return 0;
}
int getCommonStrLength(char *pf,char *ps)
{
	int lenf,lens,indexf,indexs,num=-1;
	lenf=strlen(pf);
	lens=strlen(ps);
	int **cnt=new int*[lenf+1];
	for(int i=0;i<lenf+1;++i)
		cnt[i]=new int[lens+1];
	for(int i=0;i<lenf+1;++i)//第一列初始化为0
		cnt[i][0]=0;
	for(int i=0;i<lens+1;++i)//第一行初始化为0
		cnt[0][i]=0;
	for(int i=1;i<lenf+1;++i)
		for(int j=1;j<lens+1;++j)
		{
			if(pf[i-1]==ps[j-1])
				cnt[i][j]=cnt[i-1][j-1]+1;
			else
				cnt[i][j]=0;
			if(cnt[i][j]>num)
			{
				num=cnt[i][j];
				indexf=i-1;
				indexs=j-1;
			}
		}
		/*int k=num;
		char s[100];
		s[k--]='\0';
		while(indexf>=0&&indexs>=0)
		{
			if(pf[indexf]==ps[indexs])
			{
				s[k]=pf[indexf];
				--k;
				--indexf;
				--indexs;
			}
			else
				break;
		}
		puts(s);*/
		for(int i=0;i<lenf+1;++i)
			delete [] cnt[i];
		delete [] cnt;
		return num;
}
提交后还是测试用例未全部通过,113分。又是什么鬼?不知道系统什么打分标准,难道是复杂度之类的?

不死心,于是搜来下面这一份,提交后223分,哇!高了很多,然并卵。还是未全部通过。不知道正确代码肿么写。

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

int getLCStringLength(string s1, string s2)
{
    if(s1 == "" || s2 == "")
        return 0;

    int m = s1.size();
    int n = s2.size();
    vector<vector<int> > table(m+1, vector<int>(n+1));

    int biggest = 0;  // 记录表中最大值
    for(int i=0; i<m+1; ++i)  
    {  
        for(int j=0; j<n+1; ++j)  
        {  
            // 第一行和第一列置0  
            if (i == 0 || j == 0)  
                table[i][j] = 0;  

            else if(s1[i-1] == s2[j-1])  
            {
                table[i][j] = table[i-1][j-1] + 1;  
                if(table[i][j] > biggest)
                    biggest = table[i][j];
            }

            else  // 不相等置0
                table[i][j] = 0;  
        }  
    }
    return biggest;
}

int main ()
{
    string input, s1, s2;
    getline(cin, input);
    stringstream ss(input);
    ss >> s1;
    ss >> s2;
    cout << getLCStringLength(s1, s2) << endl;

    return 0;
}
既然是用的别人的,给出链接:http://blog.csdn.net/lisonglisonglisong/article/details/45218665

这是别人刷的2011年的OJ,但估计也木有全部通过吧。




主要是通过这道题初步了解了动态规划解决最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)问题

动态规划求解最大公共字符串问题见方案2

下面对最大公共子序列详细说明以备忘:

1、序列str1和序列str2 
  ·长度分别为m+1和n+1;
  ·创建1个二维数组L[m+1,n+1];
    ·初始化L数组0行0列内容为0
    ·m和n分别从0开始,m++,n++循环:
       - 如果str1[m] == str2[n],则L[m,n] = L[m - 1, n -1] + 1;
       - 如果str1[m] != str2[n],则L[m,n] = max{L[m,n - 1],L[m - 1, n]}
    ·最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
    ·从数组L中找出一个最长的公共子序列

   2、从数组L中查找一个最长的公共子序列

   i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
  ·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
  ·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)

直接在方案2基础上稍作改动即可:
#include<iostream>
using namespace std;
#define N 1000
int getCommonStrLength(char*,char*);
int main()
{
	char pFirstStr[N],pSecondStr[N];
	gets(pFirstStr);
	gets(pSecondStr);
	cout<<getCommonStrLength(pFirstStr,pSecondStr);
	system("pause");
	return 0;
}
int getCommonStrLength(char *pf,char *ps)
{
	int lenf,lens,indexf,indexs,max_len=-1;
	lenf=strlen(pf);
	lens=strlen(ps);
	int **cnt=new int*[lenf+1];
	for(int i=0;i<lenf+1;++i)
		cnt[i]=new int[lens+1];
	for(int i=0;i<lenf+1;++i)//第一列初始化为0
		cnt[i][0]=0;
	for(int i=0;i<lens+1;++i)//第一行初始化为0
		cnt[0][i]=0;
	for(int i=1;i<lenf+1;++i)
		for(int j=1;j<lens+1;++j)
		{
			if(pf[i-1]==ps[j-1])
				cnt[i][j]=cnt[i-1][j-1]+1;
			else
				{
					if(cnt[i][j-1]>cnt[i-1][j])
						cnt[i][j]=cnt[i][j-1];
					else
						cnt[i][j]=cnt[i-1][j];
				}
			if(cnt[i][j]>max_len)
				{
					max_len=cnt[i][j];
					indexf=i;
					indexs=j;
				}
		}
		int k=max_len;		
		char s[1000];
		s[k--]='\0';
		while(indexf>=0&&indexs>=0)
		{
			if(pf[indexf-1]==ps[indexs-1])
			{
				s[k]=pf[indexf-1];
				--k;
				--indexf;
				--indexs;
			}
			else
			{
				if(cnt[indexf][indexs-1]>cnt[indexf-1][indexs])
					--indexs;
				else
					--indexf;
			}
		}
		puts(s);
		for(int i=0;i<lenf+1;++i)
			delete [] cnt[i];
		delete [] cnt;
		return max_len;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值