- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
有人能解释一下从后缀数组构造 LCP 的代码是如何工作的吗? suffixArr[]
是一个数组,使得 suffixArr[i]
保存字符串中具有等级 i 的后缀的索引值。
void LCPconstruct()
{
int i,C[1001],l;
C[suffixArr[0]] = n;
for(i=1;i<n;i++)
C[suffixArr[i]] = suffixArr[i-1];
l = 0;
for(i=0;i<n;i++)
{
if(C[i]==n)
LCPadj[i] = 0;
else
{
while(i+l<n && C[i]+l<n && s[i+l] == s[C[i]+l])
l++;
LCPadj[i] = l;
l = max(l-1,0);
}
}
for(i=0;i<n;i++)
cout<<LCPadj[suffixArr[i]]<<"\n";
}
最佳答案
首先,重要的是要意识到算法按原始顺序处理后缀,即它们在输入字符串中出现的顺序。不按字典顺序排列。
所以如果输入字符串是 abxabc
,它首先考虑 abxabc
,然后 bxabc
,然后 xabc
等等。
对于它按此顺序考虑的每个后缀,它确定作为其词典前驱 (*) 的后缀的位置(因此,在这里,并且仅在此处,它使用词典顺序的概念)。对于第一个后缀 abxabc
,字典序的前身,即在后缀的字典序中直接出现在它之前的后缀是 abc
.它通过在数组 C
中的 O(1) 查找来确定这一点。 ,这是专门为此目的准备的。
内循环比较abxabc
的字符和 abc
一一确定这两个后缀的前2个字符是相同的。这是变量 l
在您的代码中,这意味着 LCP 中后缀 abxabc
的条目必须是 2,所以我们设置 LCPadj[i] = l
.请注意 i
这里指的是后缀在输入字符串中的位置,而不是它在后缀数组中的位置。所以LCPadj
不是 LCP 阵列(还)。它是一种辅助数据结构。
然后它继续下一个字符串,即 bxabc
.它再次使用 C
找到bc
是其字典序的前身,然后确定两者共享多少前缀字符。诀窍来了:可以肯定,这必须至少与上一步中的一样多(即 2),减去 1。为什么?因为我们目前考虑的字符串,bxabc
, 当然是之前考虑的字符串 ( abxabc
) 的后缀,因此该字符串的字典前身 ( abc
) 也必须有一个短 1 个字符的后缀 ( bc
),并且该后缀也必须位于后缀数组中的某个位置,并且它必须与当前考虑的字符串共享其前缀,减去第一个字符。此外,不可能有任何其他后缀既更短又在字典上更接近当前考虑的字符串。如果您考虑字典排序的工作原理,后者是非常合乎逻辑的,但也有正式的证明(例如 Kärkkäinen 讲座中的引理 5.10 here)
所以这描述了这里工作的主要原则。为了充分理解每个变量的作用,您的代码有几点需要注意:
C
是一个辅助数组(长度为 n
整数),它为输入字符串中的每个后缀存储其他后缀的位置,该后缀是其直接的字典序前辈。这个数组不是从左到右构造的,而是(明智地)通过从左到右遍历后缀数组,因为这样可以很容易地确定任何字符串的直接字典序前身:从位置开始的后缀的直接字典序前身suffixArr[i]
当然必须位于位置 suffixArr[i-1]
.在您的代码中确认这是如何C
被定义为。 LCPadj
以它们在输入字符串中出现的顺序存储后缀的 LCP 值,而不是它们在后缀数组中出现的顺序。这就是为什么在输出时,LCPadj
不是从左到右打印,而是通过从左到右遍历后缀数组,并打印LCPadj[i]
以该顺序。确认是这种情况。 关于c++ - 这个从后缀数组获取 LCP 的代码是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26428636/
这似乎是一个愚蠢的问题,但为什么在许多语言中存在 ++ 和 -- 运算符的前缀和后缀版本,但是没有类似 += 或 -= 等其他运算符的前缀/后缀版本?例如,如果我能写出这段代码: myArray[x+
我需要链接到第三方预建共享库。在 Windows 上,这意味着与 Third_party.lib 链接,在 Linux/Android 上,这意味着与 libThird_party.so 链接。所以为
我正在学习 C++ 中的运算符重载。原始后缀++ 的特性是它的优先级低于赋值运算符。例如,int i=0, j=0; i=j++; cout using namespace std; class V
如何在文本区域中添加每行前缀.. 示例: 这是文本区域的内容: hello124 我想为每一行添加一个 [b] 前缀和后缀,这样当我点击一个按钮时,结果将是: [b]hello[/b] [b]124[
背景:在传统的逆波兰表示法中,所有运算符都必须具有固定长度,这使得 RPN 可以很容易地被代码评估和操作,因为每个标记、表达式和子表达式都是“自包含”的,以至于人们可以盲目地替换 y在 x y *为
我有以下旨在修改日期格式的Javascript,但是我想添加原始日期或后缀,例如“st”,“nd”,“rd”,“th”到每个结束日期编号。例如,假设我们当前的日期设置为 4 月 28 日,但我想将日期
我想制定一个 header 检查规则来添加回复并将“发件人”更改为“不回复”。我将它用于某种扩散列表地址 我试过这个正则表达式代码,但它不起作用: if !/^From:(.+@myserver\.f
我想改变数据框的列内容,以便单元格内容以列名作为前缀: > x x VarX VarY 1 A C 2 B D 3 A C 4 B D > x$V
当我执行 ipconfig/all 时,我看到 DNS 后缀搜索列表。我需要从 java 中检索该值。有谁知道如何获得它或它从哪里来? 最佳答案 DNS 后缀列表读取自 HKLM\SYSTEM\Cur
当您编写一个包含大量类的应用程序时,您是否为类名使用了前缀/后缀?还是我应该只依赖我已经定义的 namespace ? 在我的例子中,我有这样的类: Blur Contrast Sharpen Inv
大多数浏览器会像这样显示有序列表: 1. foo 2. bar 3. baz 有没有办法更改编号以改为使用前缀: #1 foo #2 bar #3 baz 最佳答案 这是我能想到的最好的,你只在 Fi
我需要批量重命名多个图像,并希望使用父目录作为基本名称。为防止一个覆盖另一个,必须添加后缀。重命名过程的顺序必须遵循文件的时间戳。因为“第一个”文件是我正在使用它的网站的特色图片。 树: └── ma
我试图使用 sed 替换文件中的一些字符串,但遇到了一个问题。 我有以下字符串: TEMPLATE_MODULE TEMPLATE_SOME_ERR TEMPLATE_MORE_ERR 我想用一些字符
我对后缀/前缀运算符的优先级 和关联性 感到困惑。 一方面,当我阅读 K&R 书时,它指出: (*ip)++ The parentheses are necessary in this last ex
我有一个具有以下结构的图 V = {A1, A2, A3, A4, A5, .., An} E = {E1, E2, E3, E4, .., Ek} 现在我们定义A1的后缀: S(A1) = {All
这是解释性代码。语言是Java,代码使用Android。 fg.setTextSize(height*0.50f); //<-'f' is in the brackets 或 @Override pr
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我正在编写自己的数组类作为练习。因为,我读到非成员函数实际上在某些方面比成员函数更好。( Scott Meyers ) 我正在尝试编写尽可能多的运算符重载作为非成员函数。运算符重载 + , - 作为非
谁能解释一下关于 C 编程语言的中缀、后缀和前缀表示法是什么? 最佳答案 这是对 three terms, and how they apply 的一个很好的讨论. C 语言几乎到处都使用中缀表示法。
我有这种情况:我需要在输入文本字段 (html) 中添加引号而不更改输入的值。我正在使用 angular,所以我使用 ngModel,它看起来像这样 我希望输入字段显示“{{data}} 中的任何内
我是一名优秀的程序员,十分优秀!