Manacher算法(马拉车)

2023-12-19

Manacher(马拉车)算法

作用:在On的时间复杂度下,求出字符串每个回文中心的最长回文半径

回文半径:以回文中心为起点,到回文串两端的距离

如:# a # b # a #

以b为回文中心,最长回文半径就是 4(可以根据个人习惯选择是否将回文中心包括)

如果回文字符串长度为偶数,那么回文中心就无法正好落在某个字符上,所以可以在每个字符之间添加一个“#”做前置处理(包括字符串首尾)

对于求一个字符串中每个字符的最长回文半径,暴力做法是使用两层循环遍历字符串的每个字符,以遍历到的字符为中心向两边扩散:

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        s = getNew(s);
        //每个位置的最长回文半径
        int[]r = new int[s.length()];
        for (int i = 0;i < s.length();i++) {
            while (i-r[i] >= 0 && i+r[i] < s.length() &&
                    s.charAt(i - r[i]) == s.charAt(i + r[i])) r[i]++;
        }
        for (int i = 0; i < s.length(); i++) {
            System.out.print(s.charAt(i)+" ");
        }
        System.out.println();
        for (int i = 0; i < s.length(); i++) {
            System.out.print(r[i]+" ");
        }

    }

    public static String getNew(String str) {
        String s = "#";
        for (int i = 0;i < str.length();i++) {
            s += str.charAt(i) + "#";
        }
        return s;
    }
}

思路

利用回文串的对称性,和之前遍历过的已知的回文串,减少中心扩散的次数,这里我们要维护一个使区间右端最靠右的区间

设有字符串S,S的l到r区间是回文串,mid为回文中心,现要求以i为回文中心的最长回文半径

i在区间 [ l , r ] 内:

j为i关于mid的对称点,那么:

  • 以 j 为中心的回文串在 [ l , r] 内
    在这里插入图片描述

    易知,r [ i ] = r [ j ]

  • 以 j 为中心的回文串有部分在[ l , r ] 外
    在这里插入图片描述

    r [ j ] 中超出 l 的那部分肯定和 r 右边不同,所以,r [ i ] = j - l + 1 = r - i + 1

  • 以 j 为中心的回文串左边界与 l 重合
    在这里插入图片描述

    这时,r [ i ] 是可以大于 r [ j ] 的,就要用中心扩散来接着求 r [ i ]

i在区间 [ l , r ] 外:

这时只能用中心扩散来求 r [ i ]

示例:洛谷:P3805 【模板】manacher

求最大回文子串长度

import java.io.*;

public class Main{
    static final int N = 22000005;
    public static void main(String[]args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        char[]c = s.toCharArray();
        char[]sc = new char[N];
        int[]d = new int[N];
        sc[0] = '#';
        int cnt = 0;
        for(int i = 0;i < c.length;i++) {
            sc[++cnt] = c[i];
            sc[++cnt] = '#';
        }
        int r = 0,len = 0,mid = 0;
        for(int i = 1;i < cnt;i++) {
            if(i <= r) d[i] = Math.min(d[(mid << 1) - i],r - i + 1);
            else d[i] = 1;
            
            while(i - d[i] >= 0 && sc[i+d[i]] == sc[i - d[i]]) d[i]++;
            
            //维护最靠右区间
            if(i + d[i] - 1 > r) {
                mid = i;
                r = i + d[i] - 1;
            }
            //这里d[i] - 1是将子串中的‘#’去掉的长度
            len = Math.max(len,d[i] - 1);
        }
        System.out.println(len);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Manacher算法(马拉车) 的相关文章

  • 使用 Tabula 通过 Python 读取 pdf 时出现 Java 错误

    我已经安装了 tabula 库 用于使用 python 将 pdf 读取到 pandas 数据框中 但是当我运行代码时 import tabula df tabula read pdf sample1 pdf pages 1 我得到了例外
  • 如何在java中将数组值排序为循环格式?

    我的数组值如下 String value 1 2 3 4 5 6 7 8 9 10 假设如果我将值 5 传递给 tat 数组 它应该按如下顺序排序 5 6 7 8 9 10 1 2 3 4 怎么办 有人帮忙吗 感谢你 你需要的就是所谓的轮换
  • 如何在 JavaFX 中连接可观察列表?

    我所说的串联是指获得一个新列表 该列表侦听所有串联部分的更改 方法的目的是什么FXCollections concat ObservableList
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • 与 Eclipse 中的 Java Content Assist 交互

    作为我的插件项目的一部分 我正在考虑与 Eclipse 在 Java 文件上显示的内容辅助列表进行交互 我正在尝试根据一些外部数据对列表进行重新排序 我看过一些有关创建新内容辅助的教程 但没有看到有关更改现有内容辅助的教程 这可能吗 如果是
  • Android studio - 如何保存先前活动中选择的数据

    这是我的代码片段 这Textview充当按钮并具有Onclicklistner在他们 当cpu1000时Textview单击它会导致cpu g1000其代码如下所示的类 public class Game 1000 extends AppC
  • 断言 Kafka 发送有效

    我正在使用 Spring Boot 编写一个应用程序 因此要写信给 Kafka 我这样做 Autowired private KafkaTemplate
  • 如何仅从 Firestore 获取最新更新的数据?

    在 Firestore 上发现任何更改时始终获取整个文档 如何只获取最近更新的数据 这是我的数据 我需要在第一次加载时在聊天中按对象顺序 例如 2018 09 17 30 40 msg和sendby 并且如果数据更新则仅获取新的msg和se
  • 从jar中获取资源

    我有包含文件的 jar myJar res endingRule txt myJar wordcalculator merger Marge class 在 Marge java 中我有代码 private static final Str
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • 在Java中运行bat文件并等待

    您可能会认为从 Java 启动 bat 文件是一项简单的任务 但事实并非如此 我有一个 bat 文件 它对从文本文件读取的值循环执行一些 sql 命令 它或多或少是这样的 FOR F x in CD listOfThings txt do
  • 蓝牙发送和接收文本数据

    我是 Android 开发新手 我想制作一个使用蓝牙发送和接收文本的应用程序 我得到了有关发送文本的所有内容逻辑工作 但是当我尝试在手机中测试它时 我看不到界面 这是Main Activity Code import android sup
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • 在 Java 中获取并存储子进程的输出

    我正在做一些需要我开始子处理 命令提示符 并在其上执行一些命令的事情 我需要从子进程获取输出并将其存储在文件或字符串中 这是我到目前为止所做的 但它不起作用 public static void main String args try R
  • Java Swing - 如何禁用 JPanel?

    我有一些JComponents on a JPanel我想在按下 开始 按钮时禁用所有这些组件 目前 我通过以下方式显式禁用所有组件 component1 setEnabled false 但是有什么办法可以一次性禁用所有组件吗 我尝试禁用
  • 为什么\0在java中不同系统中打印不同的输出

    下面的代码在不同的系统中打印不同的输出 String s hello vsrd replace 0 System out println s 当我在我的系统中尝试时 Linux Ubuntu Netbeans 7 1 它打印 When I
  • java 中的蓝牙 (J2SE)

    我是蓝牙新手 这就是我想做的事情 我想获取连接到我的电脑上的蓝牙的设备信息并将该信息写入文件中 我应该使用哪个 api 以及如何实现 我遇到了 bluecove 但经过几次搜索 我发现 bluecove 不能在 64 位电脑上运行 我现在应
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • java'assert'和'if(){}else exit;'之间的区别

    java和java有什么区别assert and if else exit 我可以用吗if else exit代替assert 也许有点谷歌 您应该记住的主要事情是 if else 语句应该用于程序流程控制 而assert 关键字应该仅用于

随机推荐