• 214. Shortest Palindrome


    一、题目

      1、审题

      

      2、分析

        给出一个字符串,在此字符串前边添加字符,使得其成为一个回文,求添加最少字符后,所形成的回文。

    二、解答

      1、思路:

        方法一、

        ①、为了处理回文字符数为奇数和偶数的问题,先在字符串 s 的每一个字符之间插入字符 '#',并将每个字符放入一个 List 中

        ②、下标 index 依次从 1 到 mid,定义两个指针 left = index - 1、right = index + 1;

          比较 left 、right 所指元素是否相等,若不相等,则 index 向后移动,若相等,则 left、right相反移动,直到 left < 0,此时,即为以 index 为中心,形成的字符串为回文。记录最大的回文中心的字符下标 index

        ③、将 ②所求得的最大 index 为中心的字符串所不包含的 s 的后部分子字符串逆序插入一个 StringBuilder 中,并将 s 插入 此 StringBuilder 中,返回。

     1    public String shortestPalindrome(String s) {
     2         
     3         List<Character> list = new ArrayList<>();
     4         list.add('#');
     5         for(char c: s.toCharArray()) {
     6             list.add(c);
     7             list.add('#');
     8         }
     9 
    10         int len = list.size();
    11         int mid = (len - 1) / 2;
    12         int i = 1;
    13         int max = 0;
    14         while(i <= mid) {
    15             int left = i - 1;
    16             int right = i + 1;
    17             while(left >= 0 && right <= len - 1) {
    18                 if(list.get(left) != list.get(right))
    19                     break;
    20                 left--;
    21                 right++;
    22             }
    23             if(left <= 0)
    24                 max = i;
    25             i++;
    26         }
    27         max = max * 2 + 1;
    28         StringBuilder sb = new StringBuilder();
    29         for (int j = len - 1; j >= max; j--) {
    30             if(list.get(j) != '#')
    31                 sb.append(list.get(j));
    32         }
    33         sb = sb.append(s);
    34         return sb.toString();
    35     }

       

      方法二、

        采用 KMP 的 Next 数组。

        ①、构造新的字符串 tmp = s + '#' + s.reverse + ‘_’; 

        ②、求出 tmp 的 KMP 算法的 Next 数组。其中 next 的最后一个元素对应的字符是 ‘_’ ,代表 ‘_’ 之前的字符串能匹配的最长前缀后缀长度 len。

          '#' 的作用是使得 '_' 对应的 next 数组值 len 不超过 s 的长度。

        ③、所求的最短回文即为: s 下标 从 len 开始的后部分子串翻转 + s 。

    以 aacecaaa 为例:

     1     public String shortestPalindrome2(String s) {
     2         
     3         String tmp = s + "#" + new StringBuffer(s).reverse().toString() + "_";
     4         int[] table = getTable(tmp);
     5         
     6         return new StringBuffer(s.substring(table[table.length - 1])).reverse().toString() + s;
     7     }
     8     
     9     
    10     private int[] getTable(String s) {
    11         int[] next = new int[s.length()];
    12         next[0] = -1;
    13         int k = -1;
    14         int j = 0;
    15         while(j < s.length() - 1) {
    16             if(k == -1 || s.charAt(k) == s.charAt(j)) {
    17                 ++k;
    18                 ++j;
    19                 next[j] = k;
    20             }
    21             else {
    22                 k = next[k];
    23             }
    24         }
    25         
    26         return next;
    27     }

      方法三、

        采用递归

        ①、找出从下标 0 开始的可能最大回文 str1,则 s 剩下子串为 str2;

        ②、str3 是 str2 的翻转,继续递归 str1,直到可以确定 str1 为一个回文,则返回的结果为 str3 + str1 + str2;

        public String shortestPalindrome3(String s) {
            
            int j = 0;
            for (int i = s.length() - 1; i >= 0; i--) {
                if(s.charAt(i) == s.charAt(j))
                    j++;
            }
            if(j == s.length())
                return s;
            String suffix = s.substring(j);
            return new StringBuffer(suffix).reverse().toString()
                        + shortestPalindrome3(s.substring(0, j)) + suffix;
                    
        }

      

      方法四、

        采用循环,判断  s 从下标 0 开始的构成的最大回文子串 str,最终将 s 中剩下的末尾的不包含在 str 中的子串进行翻转并 加上 s 返回即可。

     1     public String shortestPalindrome4(String s) {
     2         int i = 0, end = s.length() - 1, j = end;
     3         char chs[] = s.toCharArray();
     4         while(i < j) {
     5             if(chs[i] == chs[j]) {
     6                 i++;
     7                 j--;
     8             }
     9             else {
    10                 i = 0;
    11                 j = --end;
    12             }
    13         }
    14         return new StringBuilder(s.substring(end + 1)).reverse().toString() + s;
    15     }
  • 相关阅读:
    算法初步——哈希表B.1038统计同成绩学生
    算法初步——哈希表B10133.旧键盘打字 (注意bool型数组的赋值为true的方法)
    算法初步——哈希表B1029/A1084. 旧键盘
    算法初步——排序 A1012.The Best Rank(25)
    《思维导图》——东尼博赞
    算法初步——排序B1015/A1062.德才论
    入门模拟——(字符串处理)A1001. A+B Format(20)
    RMQ问题(线段树+ST算法)
    PKU 2406 Power Strings(KMP最长循环不重叠字串)
    KMP算法 kuangbin
  • 原文地址:https://www.cnblogs.com/skillking/p/9886420.html
Copyright © 2020-2023  润新知