[动态规划]最长公共子串长度问题

22 篇文章 0 订阅
18 篇文章 0 订阅

题目来自于2014.8.29阿里在线笔试题:给定一个query和一个text,均由小写字母组成。要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度。例如, query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3。请注意程序效率。


仔细分析这道题,发现就是求query和text的最长公共子串长度,是经典的动态规划问题。

F(i,j)表示以query[i]和text[j]为结尾的公共子串长度,如果query[i]!=text[j],即两个字符不等,显然不会有以两者为共同结尾的子串,因此F(i,j)=0;如果query[i]==text[j],即两个字符相等,就应该判断两者前一个字符是否相等,如果不等则说明只有这两个字符是公共子串,因此F(i,j)=1,如果相等,公共子串长度应为前一个字符的公共子串长度加1,因此F(i,j)=F(i-1,j-1)+1。

综上可知状态转移方程为:

F(i,j) = 0                ( query[i]!=text[j] )

        = F(i-1,j-1)+1 (query[i]==text[j] )

实际编程时,可开辟Q*T大小的二维数组存储计算结果,再从所有结果中取出最大值即可。

复杂度分析:Q为query长度,T为text长度,需要把每个字符两两进行比较,时间复杂度为O(Q*T),需要存储所有字符的比较结果,空间复杂度为O(Q*T)

代码如下:

/*
给定一个query和一个text,均由小写字母组成。要求在text中找出以同样的顺序连续出现在
query中的最长连续字母序列的长度。例如, query为“acbac”,text为“acaccbabb”,那么text
中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3。请注意程
序效率。
*/

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

int findMaxLenDP( const string& query , const string& text )
{
	int Qlen = query.length();
	int Tlen = text.length();
	int** F = new int*[Qlen];//二维数组,存储所有公共子串长度
	for( int i=0 ; i<Qlen ; i++ )
		F[i] = new int[Tlen];
	for( int i=0 ; i<Qlen ; i++ )
	{
		for( int j=0 ; j<Tlen ; j++ )
			F[i][j]=0;
	}

	//初始化第一行和第一列
	for( int i=0 ; i<Qlen ; i++ )
	{
		if( query[i] == text[0] )
			F[i][0] = 1;
	}

	for( int j=0 ; j<Tlen ; j++ )
	{
		if( text[j] == query[0] )
			F[0][j] = 1;
	}

	int maxSublen = 0;//存储最大公共子串长度
	for( int i=1 ; i<Qlen ; i++ )
	{
		for( int j=1 ; j<Tlen ; j++ )
		{
			//状态转移方程
			if( query[i] == text[j] )
			{
				F[i][j] = F[i-1][j-1]+1;
				maxSublen = F[i][j]>maxSublen ? F[i][j] : maxSublen;
			}
			else
				F[i][j] = 0;
		}
	}

	for( int i=0 ; i<Qlen ; i++ )
		delete[] F[i];
	delete[] F;
	return maxSublen;
}
int main()
{
	cout << findMaxLenDP( "acbac" , "acaccbabb" ) << endl;
	system("pause");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值