5. 最长回文子串

qimi_and_softkitty 2018-08-27 05:50:10
leetcode第五题,Manacher算法
两个问题:1.输入为“bb”时,我自己跑结果是bb正确,上传时显示return为空字符串
2.malloc的int型数组不能直接用free指针?

char* longestPalindrome(char* s) {
char *newStr = NULL;
char *newStrStart = NULL;
char *mvp = NULL;
char *mvq = NULL;
int *intAry = NULL;
int len = 0, maxlen = 0, pos = 1;

if(strlen(s) < 2)
return s;

/*set new str [aba] => [#a#b#a#] */
newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));
mvp = s;
mvq = newStr;
while(*mvp != '\0')
{
*mvq = '#';
*(mvq+1) = *mvp;

mvp++;
mvq = mvq + 2;
}
*mvq = '#';
*(mvq+1) = '\0';

/*cal len[i]*/
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1));

for(int i = 0 ; i <= (strlen(s) * 2 + 1); i++)
{
len = 1;
intAry[i] = 1;
mvp = newStr + i - 1;
mvq = newStr + i + 1;
if(mvp < newStr || mvq >= (newStr + strlen(newStr)))
{
continue;
}

while(*mvp == *mvq)
{
len+=1;
mvp--;
mvq++;
}

intAry[i] = len;

if(len > maxlen)
{
maxlen = len;
pos = i;
}
}

/*cal start pos*/
if(pos % 2 == 0)
{
newStrStart = s + pos/2 - maxlen/2;
}else
{
newStrStart = s + pos/2 - (maxlen/2 - 1);
}

free(newStr);
//free(intAry); 2.为什么这个free会出错
newStr = (char*)malloc(sizeof(char) * maxlen);
memcpy(newStr, newStrStart, maxlen - 1 );
newStr[maxlen-1] = '\0';

return newStr;
}
...全文
478 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
qimi_and_softkitty 2018-09-05
  • 打赏
  • 举报
回复
引用 9 楼 zangfong 的回复:
不好意思,我仔细看了代码,用不同的编译器调试了一下,确实是有问题的。你说的两个问题都是用指针模拟数组时引起的访问越界。 free(intAry)这个报错是因为申请空间不够,既然后面的for循环中i都取到(strlen(s) * 2 + 1)了,那你申请的intAry空间自然是不够了,最后访问越界了。因此要跟上面的newStr一样(strlen(s) * 2 + 2)
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));
至于你说的本地运行能够出bb,提交之后是空串,我觉得是下面的访问越界引起的: 你的代码中for循环里面的while循环中mvp--;这句在执行的时候,也一样越界了,你可以自己单步调试一下看看,就明白了
        while(*mvp == *mvq)
        {
            len+=1;
            mvp--;
            mvq++;
        }
因此这里需要加一个限制条件,以下的测试代码供参考
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* longestPalindrome(char* s) {
    char *newStr = NULL;
    char *newStrStart = NULL;
    char *mvp = NULL;
    char *mvq = NULL;
    int  *intAry = NULL;
    int   len = 0, maxlen = 0, pos = 1;

    if(strlen(s) < 2)
        return s;

    /*set new str  [aba] => [#a#b#a#] */
    newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));
    memset(newStr,0,sizeof(newStr));
    mvp = s;
    mvq = newStr;
    while(*mvp != '\0')
    {
        *mvq = '#';
        *(mvq+1) = *mvp;

        mvp++;
        mvq = mvq + 2;
    }
    *mvq = '#';
    *(mvq+1) = '\0';

    /*cal len[i]*/
    intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));
    memset(intAry,0,sizeof(intAry));
    for(int i = 0 ; i < (strlen(s) * 2 + 2); i++)
    {
        len = 1;
        intAry[i] = 1;
        mvp = newStr + i - 1;
        mvq = newStr + i + 1;
        if(mvp < newStr || mvq >= (newStr + strlen(newStr)))
        {
            continue;
        }

        while( (*mvp == *mvq) &&(mvp - newStr >= 0))
        {
            len+=1;
            mvp--;
            mvq++;
        }

        intAry[i] = len;

        if(len > maxlen)
        {
            maxlen = len;
            pos = i;
        }
    }

    /*cal start pos*/
    if(pos % 2 == 0)
    {
        newStrStart = s + pos/2 - maxlen/2;
    }else
    {
        newStrStart = s + pos/2 - (maxlen/2 - 1);
    }

    free(newStr);
    free(intAry);  //2.为什么这个free会出错
    newStr = (char*)malloc(sizeof(char) * maxlen);
    memcpy(newStr, newStrStart, maxlen - 1 );
    newStr[maxlen-1] = '\0';

    return newStr;
}

int main()
{
    char str[] = "bb";
    printf("%s\n",longestPalindrome(str));
    return 0;
}
[quote=引用 8 楼 qimi_and_softkitty 的回复:] 哎?是我编译工具有问题吗。。。 上传的时候显示input为"bb"时结果不对。。。不懂。。。
[/quote] 谢谢谢谢。通过了呢。 确实是
while(*mvp == *mvq)
        {
            len+=1;
            mvp--;
            mvq++;
        }
这里越界了。我默认为越界他们取值会不等然后退出。没有考虑到同时越界的话取值会相等。 但是
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1));
for(int i = 0 ; i < (strlen(s) * 2 + 1); i++)
这个是没有越界的哦~ 总而言之,多谢了。
zangfong 2018-08-31
  • 打赏
  • 举报
回复
不好意思,我仔细看了代码,用不同的编译器调试了一下,确实是有问题的。你说的两个问题都是用指针模拟数组时引起的访问越界。
free(intAry)这个报错是因为申请空间不够,既然后面的for循环中i都取到(strlen(s) * 2 + 1)了,那你申请的intAry空间自然是不够了,最后访问越界了。因此要跟上面的newStr一样(strlen(s) * 2 + 2)
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));


至于你说的本地运行能够出bb,提交之后是空串,我觉得是下面的访问越界引起的:
你的代码中for循环里面的while循环中mvp--;这句在执行的时候,也一样越界了,你可以自己单步调试一下看看,就明白了
        while(*mvp == *mvq)
{
len+=1;
mvp--;
mvq++;
}

因此这里需要加一个限制条件,以下的测试代码供参考
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* longestPalindrome(char* s) {
char *newStr = NULL;
char *newStrStart = NULL;
char *mvp = NULL;
char *mvq = NULL;
int *intAry = NULL;
int len = 0, maxlen = 0, pos = 1;

if(strlen(s) < 2)
return s;

/*set new str [aba] => [#a#b#a#] */
newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));
memset(newStr,0,sizeof(newStr));
mvp = s;
mvq = newStr;
while(*mvp != '\0')
{
*mvq = '#';
*(mvq+1) = *mvp;

mvp++;
mvq = mvq + 2;
}
*mvq = '#';
*(mvq+1) = '\0';

/*cal len[i]*/
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));
memset(intAry,0,sizeof(intAry));
for(int i = 0 ; i < (strlen(s) * 2 + 2); i++)
{
len = 1;
intAry[i] = 1;
mvp = newStr + i - 1;
mvq = newStr + i + 1;
if(mvp < newStr || mvq >= (newStr + strlen(newStr)))
{
continue;
}

while( (*mvp == *mvq) &&(mvp - newStr >= 0))
{
len+=1;
mvp--;
mvq++;
}

intAry[i] = len;

if(len > maxlen)
{
maxlen = len;
pos = i;
}
}

/*cal start pos*/
if(pos % 2 == 0)
{
newStrStart = s + pos/2 - maxlen/2;
}else
{
newStrStart = s + pos/2 - (maxlen/2 - 1);
}

free(newStr);
free(intAry); //2.为什么这个free会出错
newStr = (char*)malloc(sizeof(char) * maxlen);
memcpy(newStr, newStrStart, maxlen - 1 );
newStr[maxlen-1] = '\0';

return newStr;
}

int main()
{
char str[] = "bb";
printf("%s\n",longestPalindrome(str));
return 0;
}

引用 8 楼 qimi_and_softkitty 的回复:
哎?是我编译工具有问题吗。。。
上传的时候显示input为"bb"时结果不对。。。不懂。。。

qimi_and_softkitty 2018-08-30
  • 打赏
  • 举报
回复
引用 7 楼 zangfong 的回复:
我用codeblocks运行没错 呀貌似
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* longestPalindrome(char* s) {
    char *newStr = NULL;
    char *newStrStart = NULL;
    char *mvp = NULL;
    char *mvq = NULL;
    int  *intAry = NULL;
    int   len = 0, maxlen = 0, pos = 1;

    if(strlen(s) < 2)
        return s;

    /*set new str  [aba] => [#a#b#a#] */
    newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));
    mvp = s;
    mvq = newStr;
    while(*mvp != '\0')
    {
        *mvq = '#';
        *(mvq+1) = *mvp;

        mvp++;
        mvq = mvq + 2;
    }
    *mvq = '#';
    *(mvq+1) = '\0';

    /*cal len[i]*/
    intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1));

    for(int i = 0 ; i < (strlen(s) * 2 + 1); i++)
    {
        len = 1;
        intAry[i] = 1;
        mvp = newStr + i - 1;
        mvq = newStr + i + 1;
        if(mvp < newStr || mvq >= (newStr + strlen(newStr)))
        {
            continue;
        }

        while(*mvp == *mvq)
        {
            len+=1;
            mvp--;
            mvq++;
        }

        intAry[i] = len;

        if(len > maxlen)
        {
            maxlen = len;
            pos = i;
        }
    }

    /*cal start pos*/
    if(pos % 2 == 0)
    {
        newStrStart = s + pos/2 - maxlen/2;
    }else
    {
        newStrStart = s + pos/2 - (maxlen/2 - 1);
    }

    free(newStr);
    free(intAry);  //2.为什么这个free会出错
    newStr = (char*)malloc(sizeof(char) * maxlen);
    memcpy(newStr, newStrStart, maxlen - 1 );
    newStr[maxlen-1] = '\0';

    return newStr;
}

int main()
{
    char str[] = "abcdabcba";
    //char *res=longestPalindrome(str);
    printf("%s\n",longestPalindrome(str));
    return 0;
}
哎?是我编译工具有问题吗。。。 上传的时候显示input为"bb"时结果不对。。。不懂。。。
zangfong 2018-08-29
  • 打赏
  • 举报
回复
我用codeblocks运行没错 呀貌似
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* longestPalindrome(char* s) {
char *newStr = NULL;
char *newStrStart = NULL;
char *mvp = NULL;
char *mvq = NULL;
int *intAry = NULL;
int len = 0, maxlen = 0, pos = 1;

if(strlen(s) < 2)
return s;

/*set new str [aba] => [#a#b#a#] */
newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));
mvp = s;
mvq = newStr;
while(*mvp != '\0')
{
*mvq = '#';
*(mvq+1) = *mvp;

mvp++;
mvq = mvq + 2;
}
*mvq = '#';
*(mvq+1) = '\0';

/*cal len[i]*/
intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1));

for(int i = 0 ; i < (strlen(s) * 2 + 1); i++)
{
len = 1;
intAry[i] = 1;
mvp = newStr + i - 1;
mvq = newStr + i + 1;
if(mvp < newStr || mvq >= (newStr + strlen(newStr)))
{
continue;
}

while(*mvp == *mvq)
{
len+=1;
mvp--;
mvq++;
}

intAry[i] = len;

if(len > maxlen)
{
maxlen = len;
pos = i;
}
}

/*cal start pos*/
if(pos % 2 == 0)
{
newStrStart = s + pos/2 - maxlen/2;
}else
{
newStrStart = s + pos/2 - (maxlen/2 - 1);
}

free(newStr);
free(intAry); //2.为什么这个free会出错
newStr = (char*)malloc(sizeof(char) * maxlen);
memcpy(newStr, newStrStart, maxlen - 1 );
newStr[maxlen-1] = '\0';

return newStr;
}

int main()
{
char str[] = "abcdabcba";
//char *res=longestPalindrome(str);
printf("%s\n",longestPalindrome(str));
return 0;
}
chen97423 2018-08-28
  • 打赏
  • 举报
回复
看来是我想错呢,抱歉
qimi_and_softkitty 2018-08-28
  • 打赏
  • 举报
回复
引用 2 楼 chen97423 的回复:
newStrStart = s + pos/2 - maxlen/2;你这行代码有什么用?你赋值给newstrstart的都是数字吧。
后面这里。newstrstart被用来指向回文起点~
qimi_and_softkitty 2018-08-28
  • 打赏
  • 举报
回复
引用 3 楼 chen97423 的回复:
抱歉看错呢,应该是pos和maxlen的值与s指向的地址想加超出s的范围newStrStart=s+pos/2-maxlen/2以上只是我的猜测
没有呢。我有debug哦~
chen97423 2018-08-28
  • 打赏
  • 举报
回复
抱歉看错呢,应该是pos和maxlen的值与s指向的地址想加超出s的范围newStrStart=s+pos/2-maxlen/2以上只是我的猜测
chen97423 2018-08-28
  • 打赏
  • 举报
回复
newStrStart = s + pos/2 - maxlen/2;你这行代码有什么用?你赋值给newstrstart的都是数字吧。
chen97423 2018-08-28
  • 打赏
  • 举报
回复
你的newStr字符指针为什么会传会空指针是因为你在传回去之前就已经释放掉呢

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧