查找字谜的算法 Objective-C
Posted
技术标签:
【中文标题】查找字谜的算法 Objective-C【英文标题】:Algorithm to find anagrams Objective-C 【发布时间】:2012-11-03 00:57:19 【问题描述】:我有一个算法可以在一组八个字母的单词中找到字谜。实际上,它是将较长单词中的字母按字母顺序排列,对较短的单词一个一个地执行相同操作,然后查看它们是否存在于较长的单词中,如下所示:
tower = eortw
two = otw
rot = ort
这里的问题是,如果我在eortw
中寻找ort
(或在塔中腐烂),它会找到它,没问题。腐烂在塔内被发现。但是,otw
不在eortw
内部(或两个在塔中),因为中间有 R。因此,它认为在塔中找不到两个。
有没有更好的方法可以做到这一点?我正在尝试在 Objective-C 中执行此操作,并且八个字母的单词和常规单词都存储在 NSDictionaries
中(以及它们的正常和字母形式)。
我看过其他各种帖子。 *** 上的字谜,但似乎没有一个解决这个特定问题。
这是我目前所拥有的:
- (BOOL) doesEightLetterWord: (NSString* )haystack containWord: (NSString *)needle
for (int i = 0; i < [needle length] + 1; i++)
if (!needle)
NSLog(@"DONE!");
NSString *currentCharacter = [needle substringWithRange:NSMakeRange(i, 1)];
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString: currentCharacter];
NSLog(@"Current character is %@", currentCharacter);
if ([haystack rangeOfCharacterFromSet:set].location == NSNotFound)
NSLog(@"The letter %@ isn't found in the word %@", currentCharacter, haystack);
return FALSE;
else
NSLog(@"The letter %@ is found in the word %@", currentCharacter, haystack);
int currentLocation = [haystack rangeOfCharacterFromSet: set].location;
currentLocation++;
NSString *newHaystack = [haystack substringFromIndex: currentLocation];
NSString *newNeedle = [needle substringFromIndex: i + 1];
NSLog(@"newHaystack is %@", newHaystack);
NSLog(@"newNeedle is %@", newNeedle);
【问题讨论】:
从(有序)干草堆中删除所有字母,直到并包括第一次出现的第一个字符。重复直到其中一个或其他单词为空? 抱歉,我不确定我是否理解针/干草堆的类比。能具体一点吗? 道歉。直到今天晚上我才有时间给出一个具体的例子,但是干草堆是你正在寻找的词(更长的词所以说“eortw”),而针是你正在寻找的词(你'实际上每次只寻找第一个字母,但说这是“otw”或“ort”) 好吧,我觉得有道理,我绝对可以试一试。如果您以后有更多信息,我将不胜感激,但感谢您,它应该可以工作! 【参考方案1】:如果您只使用部分字母,则不是真正的字谜。
在您的情况下,一个好的算法是获取已排序的字符串并逐字母比较它们,跳过较长单词中的不匹配项。如果您到达较短单词的末尾,那么您有一个匹配项:
char *p1 = shorter_word;
char *p2 = longer_word;
int match = TRUE;
for (;*p1; p1++)
while (*p2 && (*p2 != *p1))
p2++;
if (!*p2)
/* Letters of shorter word are not contained in longer word */
match = FALSE;
【讨论】:
【参考方案2】:这是我可能会采用的一种方法来确定一个有序词是否包含另一个有序词的所有字母。请注意,它不会找到真正的字谜(这只是要求两个有序字符串相同),但这正是我认为你所要求的:
+(BOOL) does: (NSString* )longWord contain: (NSString *)shortWord
NSString *haystack = [longWord copy];
NSString *needle = [shortWord copy];
while([haystack length] > 0 && [needle length] > 0)
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString: [needle substringToIndex:1]];
if ([haystack rangeOfCharacterFromSet:set].location == NSNotFound)
return NO;
haystack = [haystack substringFromIndex: [haystack rangeOfCharacterFromSet: set].location+1];
needle = [needle substringFromIndex: 1];
return YES;
【讨论】:
看起来不错。现在看看在Objective-C中是否存在任何形式的stringAfterIndeex或getFirstIndex .. @lukech 我想你可以使用substringFromIndex:
和rangeOfCharacterFromSet:
substringFromIndex:
会起作用,但我需要一种方法来获取该子字符串的第一个实例。到目前为止,我已经修改了添加方法。
另外,你是在返回一个方法调用吗?
这是一种递归方法,所以它的意思是“返回使用这些参数调用的这个函数的值”。我想您可以使用循环,直到其中一个或其他字符串为空。【参考方案3】:
最简单(但不是最有效)的方法可能是使用NSCountedSet
。我们可以这样做,因为对于计数集,当且仅当 [a countForObject:object] <= [b countForObject:object]
对于 a
中的每个 object
时,[a isSubsetOfSet:b]
返回 YES。
让我们添加一个类别到NSString
来做到这一点:
@interface NSString (lukech_superset)
- (BOOL)lukech_isSupersetOfString:(NSString *)needle;
@end
@implementation NSString (lukech_superset)
- (NSCountedSet *)lukech_countedSetOfCharacters
NSCountedSet *set = [NSCountedSet set];
[self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop)
[set addObject:substring];
];
return set;
- (BOOL)lukech_isSupersetOfString:(NSString *)needle
return [[needle lukech_countedSetOfCharacters] isSubsetOfSet:[self lukech_countedSetOfCharacters]];
@end
【讨论】:
以上是关于查找字谜的算法 Objective-C的主要内容,如果未能解决你的问题,请参考以下文章