leetcode214(最短パリンドローム:管理者アルゴリズム)

文字列sを指定すると、文字列の前に文字を追加して回文に変換できます。この方法で変換できる最短のパリンドロームを見つけて返します。

例1:
入力: "aacecaaa"
出力: "aaacecaaa"

解決策:文字列の接頭辞パリンドローム文字列を見つけ、残りの文字列を逆にして文字列のフロントエンドに追加します。manacherアルゴリズムを使用して、文字列の接頭辞パリンドローム文字列を見つけることができます。

class Solution {
    
    
    public String shortestPalindrome(String s) {
    
    
        int palindrome=0;
        StringBuffer S=new StringBuffer();
         /*
        * 填充字符串,在两个字符串的中间和两端填充‘#’,使得字符串的长度为奇数
        * 在字符串新的两端填充‘$’、‘!’、防止越界问题
        * 遍历新字符串,以新字符串的每个字符为中心,向外扩展,记录回文字符串的最大半径
        * 回文字符串的长度:回文字符串半径-1
        */
        for(int i=0;i<s.length();i++){
    
    
            if(i==0)
                S.append("!");
            S.append("#"+s.charAt(i));
        }
        S.append("#$");
         /*
        * 我们用int[]r保存s中以每个字符为中心的最大回文字符串半径
        * manacher算法中,我们要维护一个当前的最大回文半径rMax,和这个最大回文半径
        * 所对应的回文中心center,以及最大边界(right=center+rMax-1),如果当前的字符串中心k在
        * 最大边界内(k<edge),则Math.min(r[2*center-i],right-i)一定在k的回文字符串半径范围内,
        * 可以设此为向外扩展的初始值,以减少程序运行次数(利用已知回文字符串优化程序运行)
        */
        int rMax=1;
        int center=0;
        int right=0;
        int[]r=new int[S.length()];
        for(int i=1;i<S.length()-1;i++){
    
    
            if(i<=right)
                r[i]=Math.min(r[2*center-i],right-i+1);
            else
                r[i]=1;
            while(S.charAt(i-r[i])==S.charAt(i+r[i])){
    
    
                r[i]++;
            }
            if(r[i]>rMax||i>right){
    
    
                center=i;
                rMax=r[i];
                right=rMax+center-1;
            }
            //如果r[i]==i,则说明是前缀回文字符串
            if(r[i]==i)
                palindrome=r[i]-1;
        }
        String add=palindrome==s.length()?"":s.substring(palindrome);
        return new String(new StringBuffer(add).reverse().toString()+s);
    }
}

おすすめ

転載: blog.csdn.net/CY2333333/article/details/108312614