两个字符串的相关问题

关于两个字符串进行匹配最长公共字串等问题很多,本文就是记录我遇到的相关问题,并记录之。

这类问题一般都是使用动态规划。需要注意边界情况和下标

(1)最长公共字串(连续)

string a= "abcdef";

string b = "abdef";

可以使用动态规划来解决,使用一个二维数组,状态d[i,j]表示到a[i]和b[j]的最长公共字串,这样问题就是要找出状态转移方程。

如果a[i] = b[j] 那么,d[i,j] = d[i-1,j-1]+1

如果a[i] != b[j] 那么 ,d[i,j] = 0

最后再遍历一下数组,来找出最大的字串。


优化,首先,遍历找出最大字串这一步可以放到计算过程中。

string LCS(string s1, string s2){
		int len1 = s1.length();
		int len2 = s2.length();
		int maxLength = 0;
		int index = 0;
		int table[1005][1005];
		for (int i = 1 ; i < len1+1 ; i++)
			table[i][0] = 0;
		for (int i = 1 ; i < len2+1 ; i++)
			table[0][i] = 0;
		for (int i = 1 ; i <= len1 ; i++){
			for (int j = 1 ; j <= len2 ; j++){
				if (s1[i-1] == s2[j-1]){
					table[i][j] = table[i-1][j-1] + 1;
				}else{
					table[i][j] = 0;
					//table[i][j] = (table[i-1][j] > table[i][j-1]) ? table[i-1][j] : table[i][j-1];
				}
				if (table[i][j] > maxLength ){
					maxLength = table[i][j];
					index = i;
				}

			}
		}
		return s1.substr(index-maxLength,maxLength);
}


例外,一般的动态规划的计算空间都可以降低。将二维空间降至一维空间。

降维对于j一般是正序和逆序,关键是看,如果在计算过程中j-1会被提前计算,则要以相反的顺序进行。比如上面,状态转移是

table[i][j] = table[i-1][j-1] + 1;
如果j是从0 到 len2进行,那么table[j-1]就会被先计算,可是从状态转移我们知道,应该在计算table[j]时,这一行的table[j-1]仍是上一行的,所以应该倒过来进行。
<pre name="code" class="cpp">string LCS_continue(string s1,string s2){
	int len1 = s1.size();
	int len2 = s2.size();
	vector<int> result(len2+1);
	int longest = 0;
	int index = 0;
	for (int i = 0 ; i < len2+1; i++)
		result[i] = 0;
	for (int i = 0 ; i < len1; i++){
		for (int j = len2-1 ; j >=0; j--){
			if (s1[i] == s2[j]){
				cout<<i<<" "<<j<<endl;
				result[j+1] = result[j]+1;
			}else{
				result[j+1] = 0;
			}
			if (result[j+1] > longest){
				longest = result[j+1];
				index = j+1;
			}
		}
	}
	return s2.substr(index-longest,longest);
}

(2)公共最长子序列(非连续)

非连续的状态转移也很容易得到

d[i,j] = d[i-1,j-1]+1 (a[i] == b[j])

d[i,j] = max(d[i-1,j],d[i,j-1]) (a[i] != b[j])

同样,在降维的时候,j仍是要逆序进行。

</pre><pre code_snippet_id="616917" snippet_file_name="blog_20150311_10_3656662" name="code" class="cpp"><pre name="code" class="cpp">int LCS_not_continue(string s1,string s2){
	int len1 = s1.size();
	int len2 = s2.size();
	vector<int> result(len2+1);
	for (int i = 0 ; i < len2+1; i++)
		result[i] = 0;
	for (int i = 0 ; i < len1; i++){
		for(int j = len2-1 ; j >= 0; j--){
			if (s1[i] == s2[j]){
				result[j+1] = result[j]+1;
			}else{
				result[j+1] = max(result[j],result[j+1]);
			}
		}
	}
	return result[len2];
}

(3)LeetCode Edit Distance

这题仍可以使用动态规划,问题是,如何得到转移方程。

if a[i] == b[j] then d[i,j] = d[i-1,j-1] 

但是不相等的情况下如何计算呢

题目给出了三种可能方式,结果就是根据这三种方式进行

if a[i] != b[j] then min(

a[i-1,j]//相当于删除a[i-1]

a[i,j-1]//相当于插入a中

a[i-1,j-1]//相当于替换

)

<pre name="code" class="cpp">int minDistance(string word1,string word2){
		int m = word1.size();
		int n = word2.size();
		vector<vector<int> > result(m+1,vector<int>(n+1));
		for (int i = 0 ; i <= m ; i++)
			result[i][0] = i;
		for (int j = 0 ; j <= n ; j++)
			result[0][j] = j;
		for (int i = 0; i < m; i++){
			for (int j = 0 ; j < n ; j++){
				if (word1[i] == word2[j])
					result[i+1][j+1] = result[i][j];
				else
					result[i+1][j+1] = min(result[i][j+1],min(result[i+1][j],result[i][j]) )+1;

			}
		}
		return result[m][n];
	}


 




 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值