Manecher算法

一、概念介绍

1.回文半径,例 aabxbcc,xbcc为回文半径
2.回文直径 ,例 aabxbcc,aabxbcc为回文直径
3.最右回文边界,记录最右回文边界的位置。R
4.取得最右回文边界的中心C。

二、Manecher算法

这里先对字符串处理下,每个字符中间填充个字符’#’

分情况讨论,i表示每个字符串index
1.i 在 R外 如:abcbad

i的回文半径只能暴力往外扩
                    R'    C     R      
              d  b  a  b  x  b  a  c  x
                                   i   

2.i 在 R内: i’ 表示 i 基于 C 的对称点,R‘ 表示 R基于C的对称点
1). i’ 的最左回文边界在 R‘ 内 :

i'的回文半径是2,可以推出i的回文半径也是2
              R'          C          R
              c  b  a  b  x  b  a  b c
                    i'          i     
2). i' 的最左回文边界 在 R' 外 :
i'的回文半径是3,可以推出i的回文半径也是R - i + 1
                 R'       C        R
              x  b  a  b  x  b  a  b  c
                    i'          i     
3)  i' 的最左回文边界在 R' 上 :
i'的回文半径是2,可以推出i的回文半径最短也是2.但是可以往外扩
                 R'       C        R   
              d  b  a  b  x  b  a  b  x
                    i'          i      

三、相关代码如下

char *get_deal_str(char *str)
{
    char *buf = malloc(sizeof(char) * strlen(str) * 2 + 1);
    memset(buf, '#', sizeof(char) * strlen(str) * 2 + 1);
    for (int i = 1; i < strlen(buf); i = i + 2) {
        buf[i] = str[ i / 2];
    }
    return buf;
}

int get_max(int a, int b)
{
    return a > b ? a : b;
}

/* 若匹配返回下标,若不匹配返回-1 */
int manager(char *str)
{
    if (str == NULL || strlen(str) == 0) {
        return -1;
    }
    char *arr = get_deal_str(str);
    int len = strlen(arr);
    int R = -1;
    int i = 0;
    int C = -1;
    int max = 0;
    int size[len]; /* 求的是回文半径 */
    for (i = 0; i < len; i++) {
        size[i] = i < R ? get_min(size[2 * C - i], R - i) : 1;
        while (i + size[i] < len && i - size[i] >= 0) {
            if (arr[i + size[i]] == arr[i - size[i]]) {
                size[i]++;
            } else {
                break;
            }
        }

        if (i + size[i] > R) {
            R = i + size[i];
            C = i;
        }
        max = get_max(max, size[i]);
    }

    return max - 1;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值