zoukankan      html  css  js  c++  java
  • 找出字符串中的最长回文

    对于字符cabadabae来说,已有的回文有aba, ada,abadaba。最长的显然是abadaba。如果简单点要找出最长的回文。可以用遍历的方式,时间负责度将是O(n^3)。为了降低时间负责度,我们就必须采用另外的方式。由于回文是左右对称的,因此我们可以利用左右对称的这个特性来寻找答案

    对于字符串cabadabae来说。已经知道了第三位为中心的aba和第5位为中心的abadaba是回文。已知第5位为中心的abadaba是回文,由回文的特性,就能够知道2-4位和6-8位对称,而又知道第3位为中心的aba是回文,所以2-4位是回文。这样的话,6-8位肯定是回文。

    那么如果我们要判断第6位为中心的回文的时候,该如何进行呢

    cabadabae             3-4于6-7位对称

    cabadabae             而第四位的a回文长度为1

    cabadabae             可以推断出第6位的回文长度也是1

    那么也就是说以第6位为中心的回文其实不需要扩展,我们可以直接知道回文长度为1。那么以第7位为中心的回文是否需要向两边扩展继续寻找呢。答案是需要的。因为我们已经知道6-8位是回文,也就是以第7位为中心的回文长度至少为3。但是第9位是什么不知道,因此需要扩展边界。

    对应代码如下:

     

    char *insertsymtostring(char *s)

    {

        char *newstr;

        int len,len1,i,j;

        len = strlen(s);

        len1 = 2 * len - 1;

        j = 0;

        newstr = (char *)malloc(len1 * sizeof(char));

        for (i = 0; i < len1; i+=2)

        {

            newstr[i] = s[j];

            newstr[i + 1] = '#';

            j++;

        }

        newstr[i-1] = '';

        return newstr;

    }

     

    char *reverfindLongestPlalindromeStringseKGroup(char *s)

    {

        char *s1,*s2;

        int i,len,rightside,rightsidecenter,center,longesthalf, needCalc,j;

        rightside = rightsidecenter = 0;

        center = longesthalf = 0;

        int *halflenarr;

        //将字符之间插入#

        s1 = insertsymtostring(s);

        len = strlen(s1);

        halflenarr = (int *)malloc(len * sizeof(int));

        memset(halflenarr, 0, len*sizeof(int));

        s2 = (char *)malloc(len*sizeof(char));

        j = 0;

        for (i = 0; i < len; i++)

        {

            needCalc = 1;

            if (rightside > i)

            {

                 //回到与之对称的左边符号位置,根据对称的左边符号的回文长度得到当前的回文长度

                 int leftcenter = 2 * rightsidecenter - i;

                 halflenarr[i] = halflenarr[leftcenter];

                 if (i + halflenarr[i] > rightside)

                 {

                     halflenarr[i] = rightside - i;

                 }

                //如果扩展后的边界小于回文的最大边界rightside, 则表明不需要扩展边界

                 if (i + halflenarr[leftcenter] < rightside)

                 {

                     needCalc = -1;

                 }

            }

            //计算以每个字符为中心的回文长度,计算右边界和center位置。halflenarr存储回文长度的一半

            if (needCalc == 1)

            {

                 while (i - 1 - halflenarr[i] >= 0 && i + 1 + halflenarr[i] < len)

                 {

                     if (s1[i + 1 + halflenarr[i]] == s1[i - 1 - halflenarr[i]])

                     {

                         halflenarr[i]++;

                     }

                     else

                         break;

                 }

                 rightside = i + halflenarr[i];

                 rightsidecenter = i;

                 if (halflenarr[i] > longesthalf)

                 {

                     center = i;

                     longesthalf = halflenarr[i];

                 }

            }

        }

     

     

        //根据当前得到的重点位置和最大回文长度的一般,来得到回文字符

        for (i = center - longesthalf; i <= center + longesthalf; i += 2)

        {

            s2[j] = s1[i];

            j++;

        }

        printf("center=%d ", center);

        printf("center_value=%c ", s1[center]);

        printf("longesthalf=%d ",longesthalf);

        s2[j] = '';

        printf("s2=%s ", s2);

        return s2;

    }

  • 相关阅读:
    10年后我又来看看我自己!
    KubernetesKuboard
    VSCode SSH 免密登录
    Windows Terminal 使用 PuTTY 连接 COM 串口
    PuTTY SSH 免密登录
    FastDDS 安装过程的坑🕳坑🕳坑🕳坑🕳坑🕳坑🕳
    Samba 安装、配置、共享 home 目录、创建用户、设置密码、映射盘符
    Win10 恢复快捷方式小箭头
    CSAPP 并发编程读书笔记
    修改 VSCode 终端配色
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/11529252.html
Copyright © 2011-2022 走看看