非动态规划实现LCS算法

LCS(最长公共子串 longest common subsequence)一般都会采用动态规划的算法来实现,算法的时间复杂度大概是O(x2),  另外需要一个x2的额外空间, 这个算法这里我不做说明,给个讲得不错的教程地址

LCS教程

 

这边博文里我将给出一个不采用动态规划的算法,并且时间复杂度和动态规划算法相同,还不会使用到额外的空间,空间复杂度为O(0)。

 

思路:

假设存在两个字符串l和r, 并且strlen(l) <= strlen(r),

将l字符串想象成一辆车,

将r字符串想象成公路,

车从公路的左边开到右边,

从左边-->右边的这个过程中字符串l和r中相同的部分总会有重合的情况, 统计出最大的串的长度。

--->开始

Car(字符串l)  ---------------

Road(字符串r)              ----------------------------------------------------

                                                                                Car(字符串l)  ---------------(终点)

 

在移动的任何一步里都可以检测到子串重合的情况。 比如在移动的过程中如下图,在这个状态发现红色下划线那部分子串相同, 检测这个状态只要时间复杂度O(N), N为l字符串的长度。

                       ---------------

                                    ----------------------------------------------------

 

 

  代码如下: 

int lcs(const char *s1, int n1, const char *s2, int n2) {
	int i, steps, ln, rn;
	int max;
	int moves;
	const char *l;
	const char *r;

	if (n1 < n2) {
		l = s1; r = s2; ln = n1; rn = n2;
	}
	else {
		l = s2; r = s1; ln = n2; rn = n1;
	}

	max = 0;
	for (steps = 0; steps < ln + rn - 1; ++steps) {
		moves = 0;
//检测每次移动后子串重合的情况, 这里可以优化的, 我这里只是把意思表示出来, 忽略一些细节:-)
		for (i = steps; i < steps + ln; ++i) {
			if (i < ln - 1) continue;
			if (i > (ln + rn - 1) - 1) {
				max = moves > max ? moves : max;
				break;
			}

			if (l[i - steps] == r[i - ln + 1]) {
				++moves;
				max = moves > max ? moves : max;
			}
			else {
				max = moves > max ? moves : max;
				moves = 0;
			}
		}
	}	

	return max;
}

  

 

posted @ 2016-03-23 00:44  canbin.zhang  阅读(811)  评论(0编辑  收藏  举报