- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
给定一个 suffix array ,来自 SRM 630 的 TopCoder 任务要求找到字符串中不同字符的最小数量,这些字符可以形成具有给定后缀数组的字符串。 full problem statement can be found on the TopCoder website .
这是ftiasch写的算法:
public int minimalCharacters(int[] array) {
int n = array.length;
int[] position = new int[n + 1];
for (int i = 0; i < n; ++i) {
position[array[i]] = i;
}
position[n] = -1;
int[] minimum = new int[n + 1];
for (int i = n - 1; i >= 0; --i) {
minimum[i] = Integer.MAX_VALUE;
for (int j = i + 1; j <= n; ++j) {
boolean valid = true;
for (int x = i; x < j; ++x) {
for (int y = x + 1; y < j; ++y) {
valid &= position[array[x] + 1] < position[array[y] + 1];
}
}
if (valid && minimum[j] < Integer.MAX_VALUE) {
minimum[i] = Math.min(minimum[i], minimum[j] + 1);
}
}
}
return minimum[0];
}
我知道这是一个动态规划算法,但它是如何工作的?我真的需要帮助来理解它。
这是 ftiasch 给我的回信:
hi Ariel,
First of all, thanks to your compliment. Frankly speaking, my solution is not the best solution to the problem. The optimal one runs in O(n) time but mine takes O(n^4). I just picked this idea during the contest because n is relatively small.
Keep in mind that same characters become continuous in the SA. Since the problem asked for the least number of characters, so I decided to use dynamic programming to partition the SA into consecutive segments so that each segments start with the same character.
Which condition is necessary for S[SA[i]] == S[SA[j]] assumed that i < j? The lexicographic comparison suggests that suffix(SA[i] + 1) should be smaller than suffix(SA[j] + 1). We can easily find that the condition is also sufficient.
Write to me if you have any other question. :)
感谢 David,我们终于成功了。这是来自 David 的 Python 版本的 java 中的线性时间算法:
public int minimalCharacters(int[] array) {
int n = array.length, i;
if (n == 0)
return 0;
int[] array1 = new int[n + 1];
for (i = 0; i < n; i++)
array1[1 + i] = array[i];
int[] position = new int[n + 1];
for (i = 0; i < n + 1; i++)
position[array1[i]] = i;
int k = 1;
for (i = n; i > 1; i--) {
if (position[array1[i] + 1] <= position[array1[i - 1] + 1])
k++;
}
return k;
}
最佳答案
这是一个二次时间算法。后缀数组指定每个一对后缀 他们如何按字典顺序比较(和空的后缀总是小于所有的)。让s
是未知字符串并假设我们正在比较后缀 s[i...]
带后缀 s[j...]
.如果s[i] != s[j]
, 然后比较 s[i]
和 s[j]
解决它。否则,结果与我们比较 s[i+1...]
相同。和 s[j+1...]
.
假设我们希望确保s[i...] < s[j...]
.显然我们需要 s[i] <= s[j]
.事实上,除非 s[i+1...] < s[j+1...]
,我们需要严格不等式s[i] < s[j]
,否则决胜局将进入错误的方法。否则,s[i] == s[j]
不管其余的就足够了的字符串。将所有不等式收集为有向弧顶点对应于 s
中的位置的图.这个图是根据后缀的总顺序必然是非循环的。使每个弧长如果不等式是严格的则为 1,否则长度为 0。输出长度最长路径的加一(如果图形为空,则为零)。
相应的至少需要这么多不同的字母不平等链。可能不太清楚的是,这么多不同的字母就足够了,但是如果我们确定每个字母的标签s
中的顶点/位置从那里开始的最长路径的长度,然后适本地标记每个弧的头部和尾部。
为了得到线性时间,我们可以利用图形。这很简单(虽然不是微不足道的;图表是指标毕竟)表明访问图中所有顶点的路径是最长的,所以我们只需要计算它的长度。
以下是示例代码 ( minChars1
) 的音译版本,直接从上面的描述( minChars2
,现在剥离所有理解用法),一个蛮力解决方案( minChars3
),以及线性时间解 ( minChars4
)。 导入 itertools
def minChars1(array):
n = len(array)
position = [-1] * (n + 1)
for i in range(n):
position[array[i]] = i
infinity = n + 1
minimum = [infinity] * (n + 1)
minimum[n] = 0
for i in range(n - 1, -1, -1):
for j in range(i + 1, n + 1):
valid = True
for x in range(i, j):
for y in range(x + 1, j):
valid = valid and position[array[x] + 1] < position[array[y] + 1]
if valid and minimum[j] < infinity:
minimum[i] = min(minimum[i], minimum[j] + 1)
return minimum[0]
def lengthOfLongestPath(graph, memo, i):
if i not in memo:
result = 0
for w, j in graph[i]:
result = max(result, w + lengthOfLongestPath(graph, memo, j))
memo[i] = result
return memo[i]
def minChars2(array):
n = len(array)
position = [-1] * (n + 1)
for i in range(n):
position[array[i]] = i
graph = {}
for i in range(n):
graph[i] = []
for j in range(n):
if position[i] > position[j]:
w = 0 if position[i + 1] > position[j + 1] else 1
graph[i].append((w, j))
memo = {None: -1}
for i in range(n):
lengthOfLongestPath(graph, memo, i)
return max(memo.values()) + 1
def minChars3(array):
n = len(array)
position = [None] * n
for i in range(n):
position[array[i]] = i
for k in range(n):
for s in itertools.product(range(k), repeat=n):
valid = True
for i in range(n):
for j in range(n):
valid = valid and (s[i:] < s[j:]) == (position[i] < position[j])
if valid:
return k
return n
def minChars4(array):
n = len(array)
if n == 0:
return 0
array1 = [n] * (n + 1)
for i in range(n):
array1[1 + i] = array[i]
position = [None] * (n + 1)
for i in range(n + 1):
position[array1[i]] = i
k = 1
for i in range(n, 1, -1):
if position[array1[i] + 1] <= position[array1[i - 1] + 1]:
k += 1
return k
def test():
for n in range(7):
for array in itertools.permutations(range(n)):
assert minChars1(array) == minChars2(array) == minChars3(array) == minChars4(array)
test()
关于java - 导致给定后缀数组的不同字符的最小数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25676463/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
为什么在 C# 中添加两个 char 结果是 int 类型? 例如,当我这样做时: var pr = 'R' + 'G' + 'B' + 'Y' + 'P'; pr 变量变为 int 类型。我希望它是
下面的代码可以编译,但 char 类型的行为与 int 类型的行为不同。 特别是 cout ::ikIsX >() ::ikIsX >() ::ikIsX >() using names
我正在寻找一个正则表达式,它可以匹配长度为 1 个或多个字符但不匹配 500 的内容。这将在 Rails 路由文件中使用,特别是用于处理异常。 路线.rb match '/500', to: 'err
对于 C 编程作业,我正在尝试编写几个头文件来检查所谓的“X 编程语言”的语法。我最近才开始,正在编写第一个头文件。这是我编写的代码: #ifndef _DeclarationsChecker_h_
为什么扩展的 ascii 字符(â、é 等)被替换为 字符? 我附上了一张图片...但我正在使用 PHP 从 MySQL 中提取数据,其中一些位置有扩展字符...我使用的是 Arial 字体。 您可以
我有一个与 R 中的断线相关的简单问题。 我正在尝试粘贴,但在获取(字符/数字)之间的断线时遇到问题。请注意,这些值包含在向量中(V1=81,V2=55,V3=25)我已经尝试过这段代码: cat(p
如何将 ANSI 字符 (char) 转换为 Unicode 字符 (wchar_t),反之亦然? 是否有用于此目的的任何跨平台源代码? 最佳答案 是的,在 中你有mbstowcs()和 wcsto
函数 fromCharCode 不适用于国际 ANSI 字符。例如,对于 ID 为 192 到 223 的俄语 ANSI (cp-1251) 字符,它返回特殊字符。如何解决这个问题? 我认为,需要将A
如果不喜欢,我想隐藏 id,但不起作用 SELECT * FROM character, character_actor WHERE character.id NOT LIKE character_a
现在这个程序成功地反转了键盘输入的单词。但是我想在我反转它之前“保存”指针中的单词,所以我可以比较两者,反转的和“原始的”,并检查它们是否是回文。我还没有太多经验,可能会出现比我知道的更多的错误,但我
Memcpy 和 memcmp 函数可以接受指针变量吗? char *p; char* q; memcpy(p,q,10); //will this work? memcmp(p,q,10); //w
恐怕我对一个相当过饱和的主题的细节有疑问,我搜索了很多,但找不到一个明确的答案来解决这个特定的明显-imho-重要的问题: 使用UTF-8将byte[]转换为String时,每个字节(8bit)都变成
我有一个奇怪的问题。我需要从 stat 命令打印输出字符串。 我已经编写了获取一些信息的代码。 import glob import os for file in glob.glob('system1
我正在使用 Java 并具有其值如下所示的字符串, String data = "vale-cx"; data = data.replaceAll("\\-", "\\-\\"); 我正在替换其中的“
String urlParameters = "login=test&password=te&ff"; 我有一个String urlParams,& - 是密码的一部分,如何使其转义,从而不被识别为分
大家好,我只想从此字符串中提取第一个字母: String str = "使 徒 行 傳 16:31 ERV-ZH"; 我只想获取这些字符: 使 徒 行 傳 并且不包括 ERV-ZH 仅数
这个问题已经有答案了: Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized point
所以, 我有一个字符**;它本质上是一个句子,带有指向该句子中每个单词的指针;即 'h''i''\0''w''o''r''l''d''\0''y''a''y''!''\0' 在这种情况下,我希望使用可
这个问题在这里已经有了答案: Using quotation marks inside quotation marks (12 个答案) 关闭 7 年前。 如何打印 " 字符? 我知道打印 % 符号
我是一名优秀的程序员,十分优秀!