最长回文子串(中间扩展法)

上一篇博文写了用三重循环暴力法求最长回文子串,这篇文章写了用中间扩展法求最长回文子串,和暴力法一样,中间扩展法最开始也需要预处理数组,仅仅把字母保留下来且全部转换成大写字母,然后用一个数组p去存这些字母在原字符串中的位置,以备输出之用,中间扩展法的时间复杂度为O(N^2)。

#include
#include
#include 
#define MAX 5000+10
using namespace std;
char buf[MAX],s[MAX],p[MAX];
int main(){
	int i,j,max=0,x,y,m=0;	
	fgets(buf,MAX,stdin);				//用fgets函数读取键盘输入的一行数据 
	for(i=0;i=0&&i+j<=m;j++){	//如果回文是奇数,这个遍历成立 
			if(s[i-j] != s[i+j])		//循环j不是遍历数组,而是从回文的中间开始往两边扩散 
				break;
			else{
				if(j*2+1>max){
					max = j*2+1;
					x=p[i-j];
					y=p[i+j];
				} 
			}
		}
		for(j=0;i-j>=0&&i+j+1<=m;j++){	//如果回文是偶数,这个遍历成立 
			if(s[i-j] != s[i+j+1])		//循环j不是遍历数组,而是从回文的中间开始往两边扩散 
				break;
			else{
				if(j*2+2>max){
					max = j*2+2;
					x=p[i-j];
					y=p[i+j+1];
				}
			} 
		}
	} 
	for(i=x;i<=y;i++)
		cout<


<think>嗯,用户让我介绍一下用蛮力法求解最长回文子串的方法。我得先忆一下蛮力法的基本思想,然后结合回文子串的特点来组织思路。首先,蛮力法通常是指尝试所有可能的解决方案,然后找出符合条件的最优解。那在最长回文子串的问题中,应该如何应用呢? 首先,回文子串的定义是正读和反读都一样的字符串。比如“aba”或者“abba”这样的结构。最长回文子串就是要找出给定字符串中最长的那个符合条件的子串。蛮力法的思路应该是检查每一个可能的子串,判断是否是文,然后记录下最长的那个。 那具体怎么实现呢?可能的步骤应该是这样的:首先,生成所有可能的子串,然后逐个检查这些子串是否为文,最后比较长度,保留最长的。这个过程的时间复杂度应该很高,因为生成所有子串需要O()的时间,而每个子串检查文又需要O(n)的时间,所以总的时间复杂度是O(),这对于较长的字符串来说效率很低。不过,作为蛮力法,这也是正常的。 接下来要考虑如何生成所有子串。假设字符串长度为n,那么子串的起始位置i可以从0到n-1,结束位置j可以从i到n-1。这样,双重循环遍历i和j就能得到所有子串。对于每个子串s[i...j],需要检查是否是文。检查的方法可以是比较子串的首尾字符,然后向中间移动,直到中间位置。如果所有对应的字符都相等,则是文。 举个例子,比如字符串“babad”,要找出所有子串,比如长度为1的每个字符都是文,长度为2的“ba”、“ab”、“ba”、“ad”等,检查是否为文,然后更长的子串,依此类推。最终找到最长的那个。 不过,这里需要注意,可能会有多个相同长度的最长回文子串,这时候可能需要返其中一个,或者全部记录,但通常题目要求返一个即可。 然后,在实现时需要考虑边界情况,比如空字符串、单字符字符串,或者整个字符串本身就是文的情况,比如“abba”这样的输入。这时候蛮力法应该能正确处理。 不过,用户可能想知道具体的步骤,所以需要分步骤解释。首先是生成所有可能的子串,然后检查每个子串是否为文,记录最长的一个。此外,可以优化检查文的部分,比如一旦发现首尾字符不匹配,就可以提前终止当前子串的检查,这样虽然不能改变时间复杂度,但能稍微减少实际运行时间。 另外,需要注意子串的索引是否正确,避免越界。比如在编程实现时,i和j的范围是否正确,子串的截取是否正确。例如,在Python中,字符串切片是s[i:j+1],因为Python的切片是左闭右开的。 可能还需要考虑如何记录最长回文子串的位置和长度。可以用变量记录当前找到的最大长度和对应的起始结束位置,每次找到更长的回文子串时更新这些变量。 总结一下,步骤大致如下: 1. 初始化最长回文子串的长度为1,起始位置为0。 2. 遍历所有可能的子串起始位置i,从0到n-1。 3. 对于每个i,遍历可能的结束位置j,从i到n-1。 4. 检查子串s[i..j]是否为文。 5. 如果是文,并且长度大于当前记录的最长长度,则更新最长长度和起始位置。 6. 遍历结束后,根据记录的起始位置和长度返最长回文子串。 然后,给出一个具体的例子,比如输入“babad”,按照这个步骤,最终找到的最长回文子串可能是“bab”或者“aba”,两者长度相同,但根据具体实现可能返其中一个。 不过,蛮力法的时间复杂度确实很高,对于长字符串来说不实用,但作为理解问题的基础方法还是有必要的。用户可能需要了解更高效的算法,比如动态规划或者中心扩展法,但当前问题只涉及蛮力法,所以需要明确说明这一点。 最后,在代码实现方面,可能需要用双重循环,然后检查文的函数。例如,Python中可以这样写: def longest_palindrome(s): n = len(s) if n == 0: return "" max_len = 1 start = 0 for i in range(n): for j in range(i+1, n): if j - i + 1 > max_len and is_palindrome(s, i, j): max_len = j - i + 1 start = i return s[start:start+max_len] def is_palindrome(s, left, right): while left < right: if s[left] != s[right]: return False left += 1 right -= 1 return True 不过,这样的代码在每次检查文时都需要遍历子串,导致时间复杂度为O()。但作为蛮力法,这就是预期的结果。需要指出这种方法在效率上的不足,但对于小规模的问题还是可行的。</think>### 蛮力法求解最长回文子串分步说明 #### 1. 问题定义 **最长回文子串**:在给定字符串中,找到长度最大的子串,且该子串正序和逆序读完全相同。例如,字符串 `"babad"` 的最长回文子串为 `"bab"` 或 `"aba"`(长度均为3)。 #### 2. 蛮力法核心思想 尝试所有可能的子串,逐一验证是否为文,并记录最长结果。 #### 3. 具体步骤 **步骤1:生成所有子串** - 用双重循环遍历字符串,生成所有可能的子串: - 外层循环:遍历起始位置 $i$($i$ 从 $0$ 到 $n-1$)。 - 内层循环:遍历结束位置 $j$($j$ 从 $i$ 到 $n-1$)。 **步骤2:验证子串是否为文** - 对每个子串 $s[i...j]$,检查其首尾字符是否对称: - 初始化两个指针 `left = i` 和 `right = j`。 - 若 $s[\text{left}] \neq s[\text{right}]$,则非文,直接终止检查。 - 否则,指针向中间移动(`left += 1`,`right -= 1`),重复比较,直到 `left >= right`。 **步骤3:记录最长文** - 维护变量 `max_length` 和 `start`,分别表示当前最长文的长度和起始位置。 - 若发现更长的回文子串,则更新这两个变量。 #### 4. 时间复杂度分析 - 生成子串:$O(n^2)$。 - 验证文:每个子串最坏需要 $O(n)$ 时间。 - **总时间复杂度**:$O(n^3)$,效率较低,仅适用于短字符串。 #### 5. 示例演示(以字符串 `"babad"` 为例) | 子串起始位置 $i$ | 子串结束位置 $j$ | 子串内容 | 是否文 | 当前最长长度 | |------------------|------------------|----------|----------|--------------| | 0 | 0 | `"b"` | 是 | 1 | | 0 | 1 | `"ba"` | 否 | 1 | | 0 | 2 | `"bab"` | 是 | 3 | | 0 | 3 | `"baba"` | 否 | 3 | | 0 | 4 | `"babad"`| 否 | 3 | | 1 | 1 | `"a"` | 是 | 3 | | 1 | 2 | `"ab"` | 否 | 3 | | 1 | 3 | `"aba"` | 是 | 3 | | ... | ... | ... | ... | ... | 最终结果:`"bab"` 或 `"aba"`(长度3)。 #### 6. 代码实现(Python) ```python def longest_palindrome(s): n = len(s) if n == 0: return "" max_length = 1 # 最短文长度为1(单个字符) start = 0 # 遍历所有子串 for i in range(n): for j in range(i, n): # 检查是否为文且长度超过当前最大值 if (j - i + 1) > max_length and is_palindrome(s, i, j): max_length = j - i + 1 start = i return s[start:start + max_length] def is_palindrome(s, left, right): # 验证子串s[left...right]是否为文 while left < right: if s[left] != s[right]: return False left += 1 right -= 1 return True ``` #### 7. 优化思路 蛮力法效率较低,实际应用中可改用以下方法: - **中心扩展法**:时间复杂度 $O(n^2)$,枚举所有可能的文中心并向两侧展。 - **动态规划**:时间复杂度 $O(n^2)$,利用已计算的子问题结果避免重复验证。 - **Manacher算法**:时间复杂度 $O(n)$,通过预处理和对称性优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值