Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何找到给定输入中的所有循环移位字符串?_String_Algorithm_Language Agnostic - Fatal编程技术网

String 如何找到给定输入中的所有循环移位字符串?

String 如何找到给定输入中的所有循环移位字符串?,string,algorithm,language-agnostic,String,Algorithm,Language Agnostic,这是一个编码练习。假设我必须决定一个字符串是否由另一个字符串的循环移位创建。例如:cab是abc的循环移位,但cba不是 给定两个字符串s1和s2,我们可以按如下方式执行: if (s1.length != s2.length) return false for(int i = 0; i < s1.length(); i++) if ((s1.substring(i) + s1.substring(0, i)).equals(s2)) return true return

这是一个编码练习。假设我必须决定一个字符串是否由另一个字符串的循环移位创建。例如:
cab
abc
的循环移位,但
cba
不是

给定两个字符串
s1
s2
,我们可以按如下方式执行:

if (s1.length != s2.length) return false for(int i = 0; i < s1.length(); i++) if ((s1.substring(i) + s1.substring(0, i)).equals(s2)) return true return false 如果(s1.长度!=s2.长度) 返回错误 对于(int i=0;i[“abc”、“xyz”、“yzx”、“cab”、“xxx”]->[“abc”、“cab”]、[“xyz”、“yzx”]、[“xxx”]


看起来我必须检查所有的字符串对。有“更好”(更有效)的方法吗?

关于在表中查找对的方法,可能有很多更好的方法,但我首先想到的是对表进行排序,并对每个相邻对进行检查


这比用表中的其他字符串检查每个字符串要好得多,也更简单。如果字符串与列表中的字符串数量相比较短,则可以通过将所有字符串旋转为某种标准形式(例如,字典最小值)来做得更好。然后按字典顺序排序并找到相同字符串的运行。那是O(n logn),我想。。。忽略字符串长度。也许可以尝试一下。

考虑为您希望测试的每个字符串构建一个自动机

每个自动机应该为字符串中的每个可能字符都有一个入口点,每个字符都有一个转换,再加上从结尾到开始的额外转换


如果混合使用自动机,您可以进一步提高性能。

首先,您可以知道字符串s1是否是字符串s2的旋转,只需调用contains(),如下所示:

public boolean isRotation(String s1, String s2){
    String s2twice = s2+s2;
    return s2twice.contains(s1);
}
也就是说,如果s1是“旋转”,s2是“旋转”,concat会给出“旋转”,其中确实包含s1

现在,即使我们假设这是线性的,或者接近它(例如,使用Rabin Karp,这不是不可能的),您仍然需要进行O(n^2)对比较,这可能太多了

您可以做的是构建一个哈希表,其中已排序的单词是键,并且发布列表包含列表中的所有单词,如果已排序,则给出键(即键(“bca”)和键(“cab”)都应返回“abc”):

私有地图索引;
/* ... */
public void buildIndex(字符串[]个字){
for(字符串字:字){
字符串sortedWord=sortWord(单词);
如果(!index.containsKey(sortedWord)){
index.put(sortedWord,newarraylist());
}
index.get(sortedWord).add(word);
}
}
警告:对于每个键,哈希表将包含所有字母完全相同且出现次数相同的单词(不仅仅是旋转,即“abba”和“baba”将具有相同的键,但isRotation(“abba”,“baba”)将返回false)


但是一旦你建立了这个索引,你可以大大减少你需要考虑的对的数量:如果你想要“bca”的所有旋转,你只需要排序(“bca”),在哈希表中查找它,然后检查(如果你想的话,使用上面的isRotation方法)如果发帖列表中的单词是不是轮换的结果。

我认为Patrick87和savinos的答案结合起来会很有意义。具体来说,在Java风格的伪代码中:

List<String> inputs = ["abc", "xyz", "yzx", "cab", "xxx"];
Map<String,List<String>> uniques = new Map<String,List<String>>();
for(String value : inputs) {
    String normalized = normalize(value);
    if(!uniques.contains(normalized)) {
        unqiues.put(normalized, new List<String>());
    }
    uniques.get(normalized).add(value);
}
// you now have a Map of normalized strings to every string in the input
// that is "equal to" that normalized version
列出输入=[“abc”、“xyz”、“yzx”、“cab”、“xxx”];
Map uniques=新映射();
for(字符串值:输入){
字符串规格化=规格化(值);
如果(!uniques.contains(标准化)){
put(标准化,newlist());
}
获取(标准化)、添加(值);
}
//现在,您有了一个规范化字符串到输入中每个字符串的映射
//这与标准化版本“相等”
如Patrick87所述,规范化字符串的最佳方法可能是选择字符串的旋转,这将导致最低的词汇顺序


然而,值得注意的是,“最佳”算法可能严重依赖于输入。。。字符串的数量、长度、重复的数量等。

您可以使用Booth算法()在O(s)时间内将所有字符串旋转为标准化形式,其中s是字符串的长度

然后,可以将规范化表单用作HashMap中的键(其中的值是在输入中看到的旋转集)。您可以在数据的一次传递中填充此HashMap。i、 例如,对于每个字符串

  • 计算归一化形式
  • 检查HashMap是否包含规范化表单作为键-如果不包含,则在此键处插入空集
  • 将字符串添加到HashMap中的集合中

然后只需要输出HashMap的值。这使得算法的总运行时间为O(n*s)——其中n是字数,s是平均字长。总空间使用率也是O(n*s)。

他的问题是
语言不可知的
。我提供了Java代码片段只是为了举例。。。我使用了哈希表和字符串,我想说解决方案也是语言无关的,不是吗?
List<String> inputs = ["abc", "xyz", "yzx", "cab", "xxx"];
Map<String,List<String>> uniques = new Map<String,List<String>>();
for(String value : inputs) {
    String normalized = normalize(value);
    if(!uniques.contains(normalized)) {
        unqiues.put(normalized, new List<String>());
    }
    uniques.get(normalized).add(value);
}
// you now have a Map of normalized strings to every string in the input
// that is "equal to" that normalized version