我正在寻找一种快速的方法来建立两个字符串的联合(就集合论而言)'字符。例如' copy'工会'令人毛骨悚然的'应该给'copyre'。我需要得到一个由很多短字符串组成的文件中使用的所有字母(我认为50个字符顶部)。
目前我:
这需要处理unicode字符,因此制作一个带有布尔值的表并标记出现的每个字母都不会起作用。任何想法如何使这更快?
答案 0 :(得分:1)
如果您需要获取所有字母,我建议使用一个bitvector,每个字母都有一个条目并标记外观。 bitvector是一个整数数组,它被解释为n-ary布尔数组,其中第n位表示第n个布尔值。访问时间是不变的。如果字符集的大小太大或不知道先验,则需要不同的集合实现。但是,在任何情况下,您都应该使用现有的数据结构(例如this one)而不是创建自己的数据结构。
算法如下所示:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
class EditorApp(App):
def build(self):
f = FloatLayout()
textinput = TextInput(text='Hello world', font_name='DroidKufi-Regular.ttf')
# import pdb; pdb.set_trace()
f.add_widget(textinput)
return f
if __name__ == '__main__':
EditorApp().run()
这是线性时间。我想,它没有变得更好。您可以通过使用巧妙的CPU对齐和并行化来获得一些常数因素 - 这取决于问题的大小。
答案 1 :(得分:0)
取第一个字符串,将每个字符放入其中一些哈希集,如java.util.HashSet
。
将第二个字符串和将每个字符放在同一个哈希集中。
迭代集合以获取" union字符串"出。该字符串可能是随机顺序。
另一个有希望的解决方案是使用专门用于整数集的数据结构 - 因为字符在某种程度上在内部表示为整数。
这样一个整数集的一个例子是Zach Tellman对Clojure的data.int-map
。它被描述为" Okasaki和Gill" Fast Mergeable Integer Maps"的直接端口,可以在http://ittc.ku.edu/~andygill/papers/IntMap98.pdf找到。" Okasaki和Gill的工作似乎是在Haskell中实现的。
在其他语言中可能存在类似的有效整数集实现。
答案 2 :(得分:0)
当你谈到输入大小的上限为50个unicode字符时(我假设你的平均情况要小得多),那么很多算法选项都出来了。我们通常会考虑裸机微优化。通过这些微小的输入大小,冒泡排序实际上可以超越快速排序。
例如,如果我们试图计算两个8个字符串之间的联合,那么构建辅助结构或在运行中执行排序的成本可能需要比保存更多的时间而不是简单的蛮力解决方案,甚至具有二次复杂性。我认为即使你可以设法重复使用相同的数据结构只是出于内存/缓存相关的原因,也可能是这样。
如果你可以预先对两个字符串进行预排序(例如:已经在文件中存储了已排序的字符串),那么你可能会得到一个改进,从那时起,两个排序字符串之间的联合可以在一个线性传递中找到(只是使用两个指针/索引)。假设您可以在这个时间关键的循环之外提前对所有这些进行排序。
否则你可能正在寻找微优化并希望在这里获取分析器。考虑到相对努力/回报率,这些中最高优先级可能与记忆有关。例如,您不希望不断地分配和释放字符串对象(并且可能会导致更多缓存未命中,具体取决于您之后的操作)来执行此操作并希望重用相同的缓冲区,除非您的字符串刚刚在硬件上分配堆栈(在这种情况下,分配/解除分配通常很便宜)。
接下来可能是多线程,但是对于这个路由,你可能希望每个线程做更多的工作,而不是计算两个很小的字符串之间的联合。调度开销可能会超过这里的好处,因此您希望每个线程/并行迭代计算多个(可能是数百个)字符串的联合。
答案 3 :(得分:0)
获得联合的快速而简单的方法是连接两个字符串,对此数组进行排序,并创建一个没有任何重复的新数组。
Java中的(未经测试的)示例是
String copy = "copy";
String creepy = "creepy";
char[] chars = (copy + creepy).toCharArray();
java.util.Arrays.sort(chars); //puts duplicates side by side
int currentChar = -1; //no risk of initial collision since chars >= 0
int setSize = 0; //set size, pointer when "compacting" the set
//ignore duplicates, reuses the char[] - garbage in the end!
for (int pos = 0; pos < chars.length; pos++) {
if (currentChar != (int)chars[pos]) {
chars[setSize] = chars[pos];
setSize++;
currentChar = chars[pos];
}
}
// please note that Strings are both immutable
// and can be held in memory for long times, don't allocate them for
// intermediate results if you can avoid it.
String result = new String(java.util.Arrays.copyOf(chars, setSize));