zoukankan      html  css  js  c++  java
  • 最长回文字串理解(学习Manacher's algorithm)

    关于字符串的子串问题,我们经常需要利用的是已经访问的部分的信息,来降低复杂度,和提高效率;在求最长回文子串的问题中,Manacher's algorithm提供了一种很好的机制,虽然部分地方不太容易理解

    先说下核心的思想:先对原字符串进行预处理,将字符串"abc"转换为"$#a#b#c#"的形式,既避免了访问越界的问题,又保证每一个字符有至少一个对称的串(真字符,或是假的“#”)

             预留两对变量(当前得到的中心位置“center”,和字符串右侧最远位置“R”,以及对称的左侧“L”)(当前访问字符位置“i”,以及相对当前访问位置“center”的对称位置“i_")

    #include <string.h>
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    void preprocess(char str[],char result[]);
    int min(int a, int b);
    int p[2020];
    int main(){
        int center,i,i_,L,R,j;
        char str[1010],result[2020];
        int maxlen, index,len;
        cin.getline(str,1000,'
    ');
        preprocess(str,result);
        /*printf("%s",result);*/
        //handle the string
        center=0,R=0;
        p[0]=0;
        len = strlen(result);
        //i from 1,so the begging position is placed '$' to avoid the segment error
        for(i=1;i<len-1;i++){
            i_=center*2-i;//the symmetric position
            L=center*2-R;
            p[i] = (R > i) ? min(R - i, p[i_]) : 0;
            while (i + p[i] + 1<len&&result[i + p[i] + 1] == result[ i- p[i] - 1])
                p[i]++;
            //if R expands,then modify it
            if (R - i <p[i]){
                center = i;
                R = i + p[i];
            }
        }
        //find the maximum length in p
        maxlen = 0, index = 0;
        for (i = 0; i < strlen(result); i++){
            if (maxlen < p[i]){
                maxlen = p[i];
                index = i;
            }
        }
        printf("%d", maxlen);
        return 0;
    }
    void preprocess(char str[],char result[]){
        int len=strlen(str),i,j;
        result[0]='$';//indicates the start 
        for(i=0,j=1;i<len;i++){
            result[j++]='#';
            result[j++]=str[i];
        }
        result[j]='#';
        result[j+1]='';
    }
    int min(int a, int b){
        if (a < b)
            return a;
        else
            return b;
    }

    p[i]记录的是位置i处的字符的右侧对称长度(包括str[i]自身),最关键的是理解这几句:

     p[i] = (R > i) ? min(R - i, p[i_]) : 0;
            while (i + p[i] + 1<len&&result[i + p[i] + 1] == result[ i- p[i] - 1])
                p[i]++;
            //if R expands,then modify it
            if (R - i <p[i]){
                center = i;
                R = i + p[i];
            }
  • 相关阅读:
    hnust Snowman
    hnust 可口可乐大促销
    hnust 聚宝盆
    hnust 搬书
    hnust 神奇的序列
    hnust 懒人多动脑
    hnust CZJ-Superman
    集合Set--BST实现
    快速排序
    位运算符
  • 原文地址:https://www.cnblogs.com/KarayLee/p/3952382.html
Copyright © 2011-2022 走看看