leetcode热题100--- P5最长回文子串(简易篇),中心扩散法(c)

题目:

                给你一个字符串 s,找到 s 中最长的回文子串。

题解:

//函数是用于中心扩散,匹配出符合规则的回文子串 
void extend(char*s, int left, int right, int *length){
    //此处主要是针对两个扩散中心的回文子串
    //超出了字符串长度就直接跳出函数 
	if (right >= strlen(s)){
        return;
    }
	/*此处为核心
	若是符合回文子串的规则,向两边进行扩散
	直到不符合条件为止
	注:此处最后得到的left、right不是正好对应着相应子串的两端
	而是会比子串左右各长一格 
	*/
    while (left >=0 && right<strlen(s) && s[left] == s[right]){
        right++;
        left--;
    }
 	//判断是否为目前最长的回文子串 
    if (right - left > length[1] - length[0]){
        length[0] = left;
        length[1] = right;
    }
    return;
}

char * longestPalindrome(char * s){
    /*这个数组是为了存储最长子串的位置
	当然这样说不准确,接着看后面就知道了 
	*/
	int length[2] ={0,0};
    //中心扩散法,循环字符串 
	for (int i=0; i<strlen(s); i++){
        extend(s, i, i, length);   //一个扩散中心 
        extend(s, i, i+1, length); //两个扩散中心 
    }
	
	/*根据最长子串的位置创造返回值的长度
	注:前面提到过,得到的left、right不是正好对应着最长回文子串的位置 
	但因为数组下标的特性及字符数组最后需要添加结束符“\0”
	得到的right、left相减正好是所需要的长度
	*/ 
    char *r = (char*)malloc(length[1] - length[0]);
    /*复制长度
	第一个参数得到复制结果的数组 
	第二个参数是被复制数组从哪里开始复制 
	第三个参数是复制多长 
	*/ 
    strncpy(r, s + length[0] + 1, length[1] - length[0] -1);
    //在末尾添上结束符 
	r[length[1] - length[0] - 1] = 0;
    return r;
}

前置知识

char *strncpy(char *dest,  const char *src,  size_t n)

  用通俗的话来说:把 src 所指向的字符串复制到 dest,最多可复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填上。

需要注意的是,strncpy 不会自动加上结束符的,需要手动加上,不然会出问题的。

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int main(){
	char string1[13] = "Hello World!";
	
	char* need_c = (char*)malloc(sizeof(string1));
	
	strncpy(need_c, string1, 6);
	printf("%s\n",need_c);
	
	strncpy(need_c, string1 + 5, 6);
	printf("%s\n",need_c);
	
	free(need_c);
}

:

回文字符串是什么?

            aba、a  诸如此类称为一个扩散中心的回文字符串

            aa、abba 诸如此类称为两个扩散中心的回文字符串

 解题思路

        因为两个扩散中心和一个扩散中心只有略微差异,故可只创建一个函数。

       我们的方法是获得所给字符串中所有的回文子串,并判断哪个是最长的子串。于是可以设计一个能够判断回文子串的函数,这个函数随着遍历所给字符串,找出所有回文子串,并动态辨别哪个是最长的。

        该函数为了区别一个扩散中心和两个扩散中心,设计滑动窗口。当为一个扩散中心时 ,初状态的左右窗口在同一个位置,若为两个扩散中心,则初状态的右窗口会比左窗口多一格。

        在所给字符串遍历结束后,根据得到的数据进行创建。因为最后得到的左、右窗口不是正好对应着相应子串的两端,而是会比最长回文子串左右两端各长一格 。但因为数组下标的特性及字符数组最后需要添加结束符“\0”,得到的左、右窗口相减正好是所需要创建存储最长回文子串的长度。


   图解

                

(两个扩散中心时,滑动窗口的初始状态)        (滑动中)

 

(一个扩散中心时,滑动窗口的初始状态)                (滑动中)

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值