求两个字符串的最长公共子串(LCS)

详细问题解说请看http://tianyunpu2008.blog.163.com/blog/static/6559379920089162236915/

 

这里是java代码实现

package edu.cumt.jnotnull;

public class Lcs {

	public static void main(String[] args) {
		char[] left = "21232523311324".toCharArray();
		char[] right = "312123223445".toCharArray();
		char [] result = delLGS(left, right);
		String strResult="";
		for(int index = 0;index<result.length;index++){
			strResult = strResult+ result[index]+"";
		}
		System.out.println(strResult);
	}

	public static char[] delLGS(char[] left, char[] right) {
		int lenLeft = left.length;
		int lenRight = right.length;
		int c[][] = new int[lenLeft][lenRight];
		char[] p;
		int start, end, len, i, j = 0;

		end = len = 0;

		for (i = 0; i < lenLeft; i++) {
			for (j = lenRight - 1; j >= 0; j--) {
				if (left[i] == right[j])// 元素相等时
				{
					if (i == 0 || j == 0)
						c[i][j] = 1;
					else {
						c[i][j] = c[i - 1][j - 1] + 1;
					}
				} else
					c[i][j] = 0;

				if (c[i][j] > len) {
					len = c[i][j];
					end = j;
				}
			}
		}

		start = end - len + 1;
		p = new char[len];
		for (i = start; i <= end; i++)
		{
			p[i - start] = right[i];
		}		
		return p;
	}
}

 衍生阅读:Rabin-Karp算法

 

Rabin-Karp算法在字符串匹配中其实也不算是很常用,但它的实用性还是不错的,除非你的运气特别差,最坏情况下可能会需要O((n-m)*m)的运行时间(关于n,m的意义请看上篇)。平均情况下,还是比较好的。

朴素的字符串匹配算法为什么慢? 因为它太健忘了,前一次匹配的信息其实可以有部分可以应用到后一次匹配中的,而朴素的字符串匹配算法只是简单的把这个信息扔掉,从头再来,因此,浪费了时间。好好的利用这些信息,自然可以提高运行速度。

这个算法不是那么容易说清楚,我举一个例子说下(看算法导论看到的例子)。

我们用E来表示字母表的字母个数,这个例子字母表如下:{0,1,2,3,4,5,6,7,8,9},那么E就是10,如果采用小写英文字母来做字母表,那么E就是26,类此。

由于完成两个字符串的比较需要对其中包含的字符进行检验,所需的时间较长,而数值比较则一次就可以完成,那么我们首先把模式(匹配的字串)转化成数值(转化成数值的好处不仅仅在此)。在这个例子里我们可以把字符0~9映射到数字0~9。比如,”423″,我们可以转化成3+E*(2+E*4)),这样一个数值,如果这个值太大了,我们可以选一个较大的质数对其取模,模后的值作为串的值。

这边处理好了,那么接下来转换被匹配的字符串,取前m个字符,如上述操作对其取值,然后对该值进行比较即可。

若不匹配,则继续向下寻找,这时候该如何做呢?比如模式是”423″,而父串是”324232″;第一步比较423跟324的值,不相等,下一步应该比较423跟242了,那么我们这步如何利用前一步的信息呢?首先我们把324前去300,然后在乘以E(这里是10),在加上2不就成了242了么?用个式子表示就是新的值a(i+1)=(E(a(i)-S[i])*h-S[S+M])) MOD p,p是我们选取的大质数,S[i]表示父串的第i个字符,而a(i)表示当前值,本例中就是324,h表示当前值最高位的权值,比如,324,则h=100,就是3这个位的权值,形式化的表示就是h=(E^m-1)MOD p。当然拉,由于采用了取模操作,当两者相等时,未必是真正的相等,我们需要进行细致的检查(进行一次朴素的字符串匹配操作)。若不相等,则直接可以排除掉。继续下一步。

 

http://www.kylogs.com/blog/archives/240.html

你可能感兴趣的:(C++,c,算法,C#,J#)