动态规划:最长连续字串

/*
	使用动态规划求解最长连续字串 
	如"abcgooglecba"与"cbagoogleabc"的最长连续字串为google 
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLEN 100

/*
	这里没有编写错误处理(字串为空,空间不足等)
	可以根据需求来进行处理,并返回相应的参数 
*/
int lcstr(const char *s1,const char *s2,char *sub)
{
	/*
		cLen记录当前最大长度
		index记录当前最大长度时字串在s1中的最大索引 
		这两个数据可以确定字串 
	*/ 
	int m,n,i,j,cLen=0,index=0;
	m=strlen(s1);
	n=strlen(s2);
	/*
		Xi={x1,x2,x3..,xi}
		Yj={y1,y2,y3..,yj}
		c[i][j]用来存储Xi和Yj的最长连续字串的长度 
	*/
	char c[MAXLEN][MAXLEN];
	memset(c,0,sizeof(c));
	
	for(i=0;i<m;++i)
	{
		for(j=0;j<n;++j)
		{ 
			//初始化首行首列 
			if(i==0||j==0)
			{
				if(s1[i]==s2[j])
					c[i][j]=1;
				else
					c[i][j]=0;
			}
			else
			{
				/*
					如果Xi最后一个元素不等于Yj最后一个元素,
					则表示当前Xi跟Yj最长子序列等于Xi-1跟Yj-1最长子序列后面加上x[i](y[j]) 
					长度等于Xi-1跟Yj-1最长子序列长度加1  
				*/
				if(s1[i]==s2[j])
				{
					c[i][j]=c[i-1][j-1]+1;
					//更新cLen跟index 
					if(cLen<c[i][j])
					{
						cLen=c[i][j];
						index=i;
					}
				}
			}
		}
	}
	strncpy(sub,s1+index-cLen+1,cLen);
	sub[cLen]='\0';
	return 0;
}

int main()
{
	char a[]="abcgooglecba";
	char b[]="cbagoogleabc";
	char sub[10];
	lcstr(a,b,sub);
	printf("%s\n",sub);
	return 0;
}

### 解决方案 在C++中,解决最长连续子串问题通常可以通过动态规划(Dynamic Programming)、滑动窗口(Sliding Window)或者前缀(Prefix Sum)等技术来实现。以下是基于这些方法的一种具体实现。 #### 动态规划解法 通过维护一个二维数组 `dp` 来记录以第 `i` 行第 `j` 列结尾的最长连续子串长度。如果当前字符匹配,则更新状态转移方程: ```cpp #include <iostream> #include <vector> using namespace std; int longestCommonSubstring(string text1, string text2) { int m = text1.size(); int n = text2.size(); vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); int maxLength = 0; for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (text1[i - 1] == text2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; maxLength = max(maxLength, dp[i][j]); } } } return maxLength; } int main() { string s1 = "abcde"; string s2 = "abycd"; cout << "The length of the longest common substring is: " << longestCommonSubstring(s1, s2) << endl; return 0; } ``` 此代码实现了两个字符串之间的最长公共子串计算逻辑[^1]。它的时间复杂度为 \(O(m \times n)\),其中 \(m\) \(n\) 是输入字符串的长度。 #### 滑动窗口优化 对于单个字符串内的最长重复子串问题,可以采用哈希集合配合双指针的方式进行求解。这种方法适用于查找具有特定属性的子串场景。 ```cpp #include <iostream> #include <unordered_set> using namespace std; bool checkRepeatingSubstrings(const string& s, int len) { unordered_set<string> seen; for (int i = 0; i + len <= s.size(); ++i) { string substr = s.substr(i, len); if (!seen.insert(substr).second) { return true; } } return false; } int findLongestRepeatedSubstring(const string& s) { int low = 1, high = s.size(); while (low <= high) { int mid = low + (high - low) / 2; if (checkRepeatingSubstrings(s, mid)) { low = mid + 1; } else { high = mid - 1; } } return high; } int main() { string inputStr = "banana"; cout << "The length of the longest repeated substring is: " << findLongestRepeatedSubstring(inputStr) << endl; return 0; } ``` 这段程序展示了如何利用二分查找加滑动窗口的方法高效定位最大重复子串长度[^2]。 --- #### 前缀辅助下的区间查询 当涉及多个区间的累加操作时,可借助前缀技巧快速完成范围统计任务。例如,在给定矩阵上的某些区域寻找满足条件的最大值组合问题中提到过类似思路[^5]。 ```cpp // 示例省略... ``` 以上仅展示部分核心概念;实际应用需视具体情况调整细节设计。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值