在 O(n) 中找到输入字符串的最小周期?

2023-11-24

鉴于以下问题:

定义 :

令 S 为字母表 Σ 上的字符串。S'是最小周期S if S'是满足以下条件的最小字符串:

S = (S')^k (S'') ,

where S''是一个前缀S。如果没有这样的S'存在,那么S是 不是周期性的。

例子 :S = abcabcabcabca. Then abcabc是一个时期以来S = abcabc abcabc a,但最小周期是abc since S = abc abc abc abc a.

给出一个算法来找到输入字符串的最小周期S或者 声明S不是周期性的。

提示:你可以这样做O(n) ...

我的解决方案:我们使用 KMP ,它的运行时间为 O(n) 。

根据问题的定义,S = (S')^k (S'') ,那么我认为如果我们创建 一个最短周期的自动机,并找到一种方法来找到最短周期,然后我就完成了。

问题是自动机的 FAIL 箭头放在哪里......

任何想法将不胜感激,

Regards


好吧,这个问题肯定可以在 O(n) 内解决,我们只需要按照你的建议巧妙地使用 KMP 即可。

解决最长的正确前缀,这也是一个后缀问题是我们将使用的 KMP 的重要组成部分。

The 最长的正确前缀,这也是一个后缀问题有点拗口,所以我们就称它为前缀后缀问题目前。

The 前缀后缀问题可能很难理解,所以我将举一些例子。

“abcabc”的前缀后缀解决方案是 “abc”,因为这是最长的字符串,也是正确的前缀 和一个正确的后缀(正确的前缀和后缀不能是整个 细绳)。

“abcabca”的前缀后缀解决方案是“a”

嗯嗯嗯嗯等一下,如果我们只是从“abcabc”末尾砍掉“a”,我们就会留下“abcabc”,如果我们得到这个新字符串的解决方案(“abc”)并再次砍掉它,我们就会留下“ abc"嗯嗯嗯嗯。非常有趣。(这几乎是解决方案,但我将讨论为什么它有效)

好吧,让我们尝试进一步形式化这种直觉,看看是否能找到解决方案。

我将在我的论证中使用一个关键假设:

我们的模式的最小周期是我们模式中每个较大周期的有效周期

让我们存储第一个的前缀后缀解决方案i我们的模式的字符lps[i]. This lps数组可以计算为O(n)它用于 KMP 算法,您可以阅读有关如何计算它的更多信息O(n) here: https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/

为了让我们清楚,我将列出一些例子lps arrays

模式:“aaaaa”

lps: [0, 1, 2, 3, 4]

模式:“aabbcc”

lps: [0, 1, 0, 0, 0, 0]

模式:“abcabcabc”

lps: [0, 0, 0, 1, 2, 3, 4, 5, 6]

好吧,现在让我们定义一些变量,来帮助我们找出为什么会这样lps数组很有用。

Let l是我们模式的长度,让k是 lps 数组中的最后一个值(k=lps[l-1])

价值k告诉我们第一个k我们的字符串的字符与最后一个相同k我们的字符串的字符。我们可以利用这个事实来找到一个时期!

使用此信息,我们现在可以显示由第一个组成的前缀l-k我们的字符串的字符形成一个有效周期。这很清楚,因为接下来k不在我们的前缀中的字符必须与第一个字符匹配k我们的前缀字符,因为我们如何定义我们的lps大批。首先k我们的前缀中的字符必须与最后一个相同k构成我们后缀的字符。

在实践中,您可以使用简单的 while 循环来实现此目的,如下所示,其中index标记您当前认为是最小句点的后缀的结尾。

public static void main(String[] args){
    String pattern="abcabcabcabca";
    int[] lps= calculateLPS(pattern);
    //start at the end of the string
    int index=lps.length-1;
    while(lps[index]!=0){
        //shift back
        index-=lps[index];
    }
    System.out.println(pattern.substring(0,index+1));
}

并且自从计算lps发生在O(n),并且您总是在 while 循环中至少后退 1 步,整个过程的时间复杂度很简单O(n)

如果您想查看下面的确切代码,我在我的calculateLPS()方法中大量借鉴了KMP的geeksForGeeks实现,但我建议您也看看他们的解释:https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/

static int[] calculateLPS(String pat) {
    int[] lps = new int[pat.length()];
    int len = 0;
    int i = 1;
    lps[0] = 0;

    while (i < pat.length()) {
        if (pat.charAt(i) == pat.charAt(len)) {
            len++;
            lps[i] = len;
            i++;
        }
        else {
            if (len != 0) {
                len = lps[len - 1];
            }
            else {
                lps[i] = len;
                i++;
            }
        }
    }
    System.out.println(Arrays.toString(lps));
    return lps;
}

最后但并非最不重要的一点是,感谢您发布如此有趣的问题,弄清楚它非常有趣!另外,我对此很陌生,所以如果我的解释的任何部分没有意义,请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 O(n) 中找到输入字符串的最小周期? 的相关文章

随机推荐

  • 在 PHP 中评估类似 MongoDB 的 JSON 查询

    考虑此 JSON 对象中表达的以下 相当复杂 查询 name Kindle Fire sale true price gt 199 lt 264 price vat bogus just to show a price vat a pric
  • 如何定期调用asyncTasks

    我有两个 AsyncTasks 执行网络操作 我想定期给他们打电话 比如一分钟后 我怎么做 我不认为我可以在 UI 线程上做到这一点 我需要创建一个新线程吗 是否可以在没有 AlarmManager Service 的情况下实现此功能 基本
  • Android 上启动完成后如何在 BroadcastReceiver 上启动 Activity

    我使用下面的代码让我的应用程序可以在启动完成 10 秒后自动启动 public class BootActivity extends BroadcastReceiver static final String ACTION android
  • 将空值排序在所有其他值之后,特殊情况除外

    我有一个带有可选排序字段的 PostgreSQL 项目表 CREATE TABLE tasks id integer PRIMARY KEY DEFAULT nextval f seq f id integer REFERENCES fix
  • Android 7 意图附加功能缺失

    有谁知道与 Android 6 0 Lollipop 相比 Android 7 0 Nougat 处理 Intent extras 的方式是否有任何变化 长话短说 我的应用程序在 4 1 16 到 6 0 23 的所有版本上都能按预期运行
  • Angular 6:HttpErrorResponse SyntaxError:JSON 中出现意外的 token

    我正在发布一个请求 我应该会收到一个 成功 字符串作为响应 我收到一个 HttpResponseError 其中包含下图中发布的以下信息 采购订单服务 postPurchaseOrderCustom purchaseOrderCustom
  • 在 PHP 中创建基于边缘检测的图像

    我很好奇 是否可以用 PHP 实现 1 发送图像文件到服务器 2 处理图像 检测边缘并根据边缘创建简单的笔画 3 将文件保存在服务器上 将其发送到用户的浏览器 其他 这是一些 示例 文件 P 如您所见 它不是使用任何启用边缘检测的程序制作的
  • GAE python 线程不并行执行

    我正在尝试在 GAE 上使用 Python 创建一个简单的 Web 应用程序 应用程序需要根据收到的请求生成一些线程 为此 我使用 python 的线程库 我生成所有线程 然后等待它们 t1 start t2 start t3 start
  • sqlalchemy 在多个列中是唯一的

    假设我有一个代表位置的类 地点 属于 客户 位置由 unicode 10 字符代码标识 位置代码 在特定客户的位置中应该是唯一的 The two below fields in combination should be unique cu
  • Odoo/OpenERP:从树视图中隐藏创建按钮

    我这里有一个情况 我正在使用 OpenERP 7 我试图从我的产品的树视图中隐藏 创建 按钮 这可以通过使用来完成
  • 隐藏的 div 高度(改变我的建议)

    好吧 我要在这里回答某人关于为什么他们的脚本不起作用的问题 他们将内容加载到隐藏的 div 中 然后获取高度 以便为包裹的 div 制作动画 但我总是尝试测试我提供的代码 所以我做了这个演示向他们证明这一点 那么 嗯 我现在是进入了暮光区还
  • 关于java字符串文字池和字符串连接的混淆

    全部 当我编写下面的代码时遇到问题 String hello Hello String str5 Hel lo String str8 Hel String str9 lo String str10 str8 str9 System out
  • 在C#中执行包含GO语句的SQL批处理

    我正在尝试构建一个程序 它可以批量执行sql语句并进行错误处理 因此我没有使用SMO 问题是GO不是 SQL 的一部分 当使用 NET 执行语句时 它最终会出现错误 SMO 会处理它 但不会给出执行是否失败的任何指示 string stat
  • 如果包含的单元格为空,则使用 jQuery 隐藏表格列

    我有一个以下类型的表 table width 500 border 1 cellspacing 0 cellpadding 0 thead tr th span 1 span th th span 2 span th th span 3 s
  • Select() 查询中使用的 Lambda 表达式

    我正在尝试构建一个 lambda 表达式 其中包含两个赋值 如下所示 然后我可以将其传递给 Queryable Select 方法 我试图将字符串变量传递到方法中 然后使用该变量构建 lambda 表达式 以便我可以在 LINQ Selec
  • 如何更新 XAMPP 的 PHP 版本 [重复]

    这个问题在这里已经有答案了 可能的重复 在 Windows 版 XAMPP 中升级 PHP 我目前使用 XAMPP 版本 1 8 1 其中 PHP 版本 5 4 3 我从一天前发布的 PHP 站点版本 5 4 11 找到了最新版本的 PHP
  • 在 Eclipse (Galileo) 中安装 Maven 插件 (m2eclipse) 时出现问题

    我已经安装了 Eclipse Galileo 适用于 Java EE 开发人员 现在我正在尝试安装 m2eclipse Maven 插件 我按照以下描述的基本步骤进行操作http m2eclipse sonatype org install
  • Django:仅更新UpdateView中已更改的字段

    我正在使用 UpdateView 来更新一系列字段 但是 我只想将已修改的字段保存到数据库中 如果在更新过程中未为字段提供值 我希望将以前的值用作默认值 如果为字段提供了新值 则只应更新该字段 我该如何实现这一目标 views py cla
  • 如何动态加载css文件

    我们正在使用Vue js and Vuetify对于我的申请 作为我的应用程序的一部分 我将根据该 API 响应在页面加载时进行 API 调用 整个应用程序将呈现所有组件 作为此 API 的一部分 我将获得名为CSS方向它告诉哪个 css
  • 在 O(n) 中找到输入字符串的最小周期?

    鉴于以下问题 定义 令 S 为字母表 上的字符串 S 是最小周期S if S 是满足以下条件的最小字符串 S S k S where S 是一个前缀S 如果没有这样的S 存在 那么S是 不是周期性的 例子 S abcabcabcabca T