1. 程式人生 > >演算法學習——尋找字串中的最長迴文子串

演算法學習——尋找字串中的最長迴文子串

文章轉載自公眾號《網際網路偵查》

/**
 * @author xiaoshi on 2018/9/24.
 * Happy Mid-Autumn Festival
 */
public class PlalindromeString {

    // 判斷一個字串是否迴文,演算法中用不到了
    @Deprecated
    private boolean isPlalindrome(String s) {
        int len = s.length();
        for(int i = 0; i < len / 2; i++) {
            if(
s.charAt(i) != s.charAt(len - 1 - i)) { return false; } } return true; } // 預處理字串,在兩個字元之間加上# private String preHandleString(String s) { StringBuffer sb = new StringBuffer(); int len = s.length(); sb.append('#'); for
(int i = 0; i < len; i++) { sb.append(s.charAt(i)); sb.append('#'); } return sb.toString(); } // 尋找最長迴文字串 public String findLongestPlalindromeString(String s) { // 先預處理字串 String str = preHandleString(s); // 處理後的字串長度 int
len = str.length(); // 右邊界 int rightSide = 0; // 右邊界對應的迴文串中心 int rightSideCenter = 0; // 儲存以每個字元為中心的迴文長度一半(向下取整) int[] halfLenArr = new int[len]; // 記錄迴文中心 int center = 0; // 記錄最長迴文長度 int longestHalf = 0; for(int i = 0; i < len; i++) { // 是否需要中心擴充套件 boolean needCalc = true; // 如果在右邊界的覆蓋之內 if(rightSide > i) { // 計算相對rightSideCenter的對稱位置 int leftCenter = 2 * rightSideCenter - i; // 根據迴文性質得到的結論 halfLenArr[i] = halfLenArr[leftCenter]; // 如果超過了右邊界,進行調整 if(i + halfLenArr[i] > rightSide) { halfLenArr[i] = rightSide - i; } // 如果根據已知條件計算得出的最長迴文小於右邊界,則不需要擴充套件了 if(i + halfLenArr[leftCenter] < rightSide) { // 直接推出結論 needCalc = false; } } // 中心擴充套件 if(needCalc) { while(i - 1 - halfLenArr[i] >= 0 && i + 1 + halfLenArr[i] < len) { if(str.charAt(i + 1 + halfLenArr[i]) == str.charAt(i - 1 - halfLenArr[i])) { halfLenArr[i]++; } else { break; } } // 更新右邊界及中心 rightSide = i + halfLenArr[i]; rightSideCenter = i; // 記錄最長迴文串 if(halfLenArr[i] > longestHalf) { center = i; longestHalf = halfLenArr[i]; } } } // 去掉之前新增的# StringBuffer sb = new StringBuffer(); for(int i = center - longestHalf + 1; i <= center + longestHalf; i += 2) { sb.append(str.charAt(i)); } return sb.toString(); } }
/**
 * @author lixin on 2018/9/24.
 */
public class Main {

    public static void main(String[] args) {

        PlalindromeString ps = new PlalindromeString();

        String[] testStrArr = new String[] {
            "abcdcef",
            "adaelele",
            "cabadabae",
            "aaaabcdefgfedcbaa",
            "aaba",
            "aaaaaaaaa"
        };

        for(String str : testStrArr) {
            System.out.println(String.format("原字串 : %s", str));
            System.out.println(String.format("最長迴文串 : %s", ps.findLongestPlalindromeString(str)));
            System.out.println();
        }

    }

}

執行結果:
原字串 : abcdcef 最長迴文串 : cdc
原字串 : adaelele 最長迴文串 : elele
原字串 : cabadabae 最長迴文串 : abadaba
原字串 : aaaabcdefgfedcbaa 最長迴文串 : aabcdefgfedcbaa
原字串 : aaba 最長迴文串 : aba
原字串 : aaaaaaaaa 最長迴文串 : aaaaaaaaa