zoukankan      html  css  js  c++  java
  • 马拉车算法

    马拉车算法用于寻找字符串中的最长回文子串。

    java

    class ManacherAlgo {
    	String longestPalindrome(String s) {
    		// 填充
    		String newS = fillStr(s);
    
    		// center是中心,right是中心的最远覆盖范围,max_center是最长回文字串的中心
    		int right = 0, center = 0, max_center = 0;
    
    		// 记录每个位置的最远覆盖范围
    		int[] radius = new int[newS.length()];
    		int lenOfNewS = newS.length();
    
    		// 算法主体
    		for (int idx = 1; idx < lenOfNewS; idx++) {
    			if (idx < right) {
    				int mirror = 2 * center - idx;
    				radius[idx] = Math.min(right - idx, radius[mirror]);
    			} else
    				radius[idx] = 1;
    
    			while (
    					(idx + radius[idx] < lenOfNewS) &&
    							(idx - radius[idx] >= 0) &&
    							(newS.charAt(idx + radius[idx]) == newS.charAt(idx - radius[idx]))
    			)
    				radius[idx]++;
    
    			if (idx + radius[idx] > right) {
    				right = idx + radius[idx];
    				center = idx;
    			}
    
    			if (radius[idx] > radius[max_center]) {
    				max_center = idx;
    			}
    		}
    
    		// 返回最长回文字串
    		int l = max_center - radius[max_center];
    		int r = max_center + radius[max_center];
    		return s.substring((l + 1) / 2, r / 2);
    	}
    
    	// 填充
    	private String fillStr(String s) {
    		StringBuilder retS = new StringBuilder("#");
    		for (int i = 0; i < s.length(); i++) {
    			retS.append(s.charAt(i)).append("#");
    		}
    
    		return retS.toString();
    	}
    
    	// 测试
    	public void testing() {
    		System.out.println(longestPalindrome("abababbb"));
    		System.out.println(longestPalindrome("aba"));
    		System.out.println(longestPalindrome("aa"));
    	}
    }
    
    public class manacher {
    
    	public static void main(String[] args) {
    		// 生成实例
    		ManacherAlgo obj = new ManacherAlgo();
    
    		// 测试
    		obj.testing();
    	}
    }
    
    

    python

    # coding=utf-8
    """
    author:shayue
    2019/09/18
    """
    
    
    class Manacher():
        """
        算法步骤:
        1. 输入要操作的字符串后,先进行填充,这一步的目的是为了无视奇偶差异,填补后的字符串长度必为奇数;
        2. 从左往右遍历,以位置center为中心,往两边扩散,记录最大回文子串的半径,比如12321,其半径为3,将半径放入列表radius中;
        3. 利用先前已经保存的半径信息,可以加快后序位置所对应回文子串的半径求解,具体实现见longest_palindromic_substring。
        """
        def __init__(self, inputStr):
            self.str_ = inputStr
            self.right = 0
            self.center = 0         #
            self.radius = None      # 列表
    
            # 下面两个变量是为了找到最长子串
            self.MaxPi = 0
            self.Max_Pi_center = 0
    
    
        def longest_palindromic_substring(self):
            """
            马拉车算法,找到最大回文子串并返回
            :return: str
            """
            filled_s = self.fill_to_s()
            self.P = [0] * len(filled_s)
            print(filled_s)
    
            for idx in range(1, len(filled_s)):
                if idx < self.right:
                    mirror = self.get_mirror(idx)
                    self.P[idx] = min(self.right - idx, self.P[mirror])
                else:
                    self.P[idx] = 1
    
                while idx - self.P[idx] >= 0 and 
                idx + self.P[idx] < len(filled_s) and  
                filled_s[idx - self.P[idx]] == filled_s[idx + self.P[idx]]:
                    self.P[idx] += 1
    
                if self.P[idx] + idx > self.right:
                    self.right = self.P[idx] + idx
                    self.center = idx
    
                if self.P[idx] > self.MaxPi:
                    self.MaxPi = self.P[idx]
                    self.Max_Pi_center = idx
    
            l = self.Max_Pi_center - self.MaxPi
            r = self.Max_Pi_center + self.MaxPi
            return self.str_[(l+1) // 2: r // 2]
    
        def get_mirror(self, i):
            """
            以self.center为中心,返回位置i对应到左边的位置mirror
            :param i: 位置i,在self.center右边
            :return: 位置mirror,在self.center左边
            """
            return 2 * self.center - i
    
        def fill_to_s(self):
            """
            对self.s进行'#'填充,填充完后的字符串总长为奇数,以便算法对奇偶情况都适用
            :return: str
            """
            retStr = "#" + "#".join(self.str_) + '#'
            return retStr
    
    
    if __name__ == '__main__':
        manacher = Manacher('abcababacab')
        print(manacher.longest_palindromic_substring())
        print(manacher.P)
    
    
    
  • 相关阅读:
    python基础---内置类型
    python基础---内置常量
    python基础---内置函数
    数据增强---CutMix
    数据增强---Mixup
    机器学习笔记---评估方法
    深度学习笔记-上溢和下溢
    线性代数笔记-子空间
    tensorflow2学习笔记---模块、层和模型
    tensorflow2学习笔记---Graph和tf.function
  • 原文地址:https://www.cnblogs.com/shayue/p/ma-la-che-suan-fa.html
Copyright © 2011-2022 走看看