数据结构与算法之Manacher算法

素颜马尾好姑娘i 2021-12-16 13:53 404阅读 0赞

数据结构与算法之Manacher算法


目录

  1. Manacher算法概述
  2. Manacher算法代码实现
  3. 扩展题——如果只能向字符串后面添加字符,怎么让整体串变成回文串,要求填的字符最少

1. Manacher算法概述

  1. Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回文子串长度的问题。
  2. 详细请见博客:https://www.jianshu.com/p/116aa58b7d81 ,写的很好,就不再复述一遍了。

2. Manacher算法代码实现

  1. public class Code_Manacher {
  2. public static char[] manacherString(String str) {
  3. char[] charArray = str.toCharArray();
  4. char[] res = new char[charArray.length * 2 + 1];
  5. int index = 0;
  6. for (int i = 0; i < res.length; i++) {
  7. res[i] = (i & 1) == 0 ? '#' : charArray[index++];
  8. }
  9. return res;
  10. }
  11. public static int maxLcpsLength(String str) {
  12. if (str == null || str.length() == 0) {
  13. return 0;
  14. }
  15. char[] charArr = manacherString(str);
  16. int[] pArr = new int[charArr.length]; //回文半径
  17. int C = -1;
  18. int R = -1;
  19. int max = Integer.MIN_VALUE;
  20. for (int i = 0; i != charArr.length; i++) {
  21. //区分情况一和情况二
  22. pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1;
  23. // 情况1 :i在R外, 暴力扩
  24. // 情况2 : i在R里, i'的回文在L,R内
  25. // 情况3 : i在R里,i'的回文在L,R外
  26. // 情况4 :i'回文左边界和L压线,从R的右边扩。
  27. //如果要验的区域没越界,并且左边区域也没越界。就再扩一下,如果是情况二和情况三,那么会失败
  28. while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
  29. //情况一,情况四
  30. if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
  31. pArr[i]++;
  32. else {
  33. //情况二,情况三
  34. break;
  35. }
  36. }
  37. if (i + pArr[i] > R) {
  38. R = i + pArr[i];
  39. C = i;
  40. }
  41. max = Math.max(max, pArr[i]);
  42. }
  43. return max - 1;
  44. }
  45. public static void main(String[] args) {
  46. String str1 = "abc1234321ab";
  47. System.out.println(maxLcpsLength(str1));
  48. }
  49. }

编译结果:
在这里插入图片描述


3. 扩展题——如果只能向字符串后面添加字符,怎么让整体串变成回文串,要求填的字符最少

  1. 代码实现

    public class Code_Manacher_ShortestEnd {

  1. public static char[] manacherString(String str) {
  2. char[] charArr = str.toCharArray();
  3. char[] res = new char[str.length() * 2 + 1];
  4. int index = 0;
  5. for (int i = 0; i != res.length; i++) {
  6. res[i] = (i & 1) == 0 ? '#' : charArr[index++];
  7. }
  8. return res;
  9. }
  10. public static String shortestEnd(String str) {
  11. if (str == null || str.length() == 0) {
  12. return null;
  13. }
  14. char[] charArr = manacherString(str);
  15. int[] pArr = new int[charArr.length];
  16. int index = -1;
  17. int pR = -1;
  18. int maxContainsEnd = -1;
  19. for (int i = 0; i != charArr.length; i++) {
  20. pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;
  21. while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
  22. if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
  23. pArr[i]++;
  24. else {
  25. break;
  26. }
  27. }
  28. if (i + pArr[i] > pR) {
  29. pR = i + pArr[i];
  30. index = i;
  31. }
  32. if (pR == charArr.length) {
  33. maxContainsEnd = pArr[i];
  34. break;
  35. }
  36. }
  37. char[] res = new char[str.length() - maxContainsEnd + 1];
  38. for (int i = 0; i < res.length; i++) {
  39. res[res.length - 1 - i] = charArr[i * 2 + 1];
  40. }
  41. return String.valueOf(res);
  42. }
  43. public static void main(String[] args) {
  44. String str2 = "abcd123321";
  45. System.out.println(str2);
  46. System.out.println(shortestEnd(str2));
  47. }
  48. }

编译结果:
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,404人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Manache算法

    今天看到这个单词就很奇怪!!撸一撸… Manacher算法的详细讲解 Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回

    相关 Manacher 算法

    0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度。 如果一个字符串正着读和反着读是一样的,那它就是回文串。下面是一些回文串的实例:

    相关 manacher算法

    manacher算法是在O(n)的复杂度内求回文串长度的算法。 算法过程如下。 先在所有字符之间加上一种没有意义的字符。 比如“\”,“|”等。来去除偶数回文和奇数回文的