基于Objective-C的字谜图查找算法

基于Objective-C的字谜图查找算法,objective-c,algorithm,nsdictionary,anagram,Objective C,Algorithm,Nsdictionary,Anagram,我有一个算法可以在一组八个字母的单词中找到字谜。实际上,它是对较长单词中的字母进行字母排序,对较短的单词逐个进行相同的排序,然后查看它们是否存在于较长的单词中,如: tower=eortw two=otw rot=ort 这里的问题是,如果我在eortw中查找ort(或在塔中腐烂),它会找到它,没有问题。在塔内发现腐烂。但是, OTW 不在代码> EORTW(或两个塔内)内,因为中间有R。因此,在塔里并没有发现两个 有更好的办法吗?我试图用Objective-C实现,八个字母的单词和常规单词都存

我有一个算法可以在一组八个字母的单词中找到字谜。实际上,它是对较长单词中的字母进行字母排序,对较短的单词逐个进行相同的排序,然后查看它们是否存在于较长的单词中,如:

tower=eortw
two=otw
rot=ort

这里的问题是,如果我在
eortw
中查找
ort
(或在塔中腐烂),它会找到它,没有问题。在塔内发现腐烂。但是,<代码> OTW 不在代码> EORTW(或两个塔内)内,因为中间有R。因此,在塔里并没有发现两个

有更好的办法吗?我试图用Objective-C实现,八个字母的单词和常规单词都存储在
NSDictionary
(以及它们的正常形式和字母顺序)中

我看了很多其他的帖子。StackOverflow上的字谜,但似乎没有一个能解决这个问题

以下是我目前掌握的情况:

- (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);
        }
    }
}
-(BOOL)doesEightLetterWord:(NSString*)haystack containWord:(NSString*)针{
对于(int i=0;i<[针长度]+1;i++){
如果(!针){
NSLog(@“完成!”);
}
NSString*currentCharacter=[指针子字符串带范围:NSMakeRange(i,1)];
NSCharacterSet*set=[NSCharacterSet characterSetWithCharactersInString:currentCharacter];
NSLog(@“当前字符为%@”,currentCharacter);
如果([haystack rangeOfCharacterFromSet:set].location==NSNotFound){
NSLog(@“字母%@未在单词%@”、currentCharacter、haystack中找到);
返回FALSE;
}否则{
NSLog(@“字母%@在单词%@”、currentCharacter、haystack中找到);
int currentLocation=[haystack rangeOfCharacterFromSet:set].location;
currentLocation++;
NSString*newHaystack=[haystack substringFromIndex:currentLocation];
NSString*newNeedle=[指针子字符串fromIndex:i+1];
NSLog(@“newHaystack是%@”,newHaystack);
NSLog(@“新针是%@”,新针);
}
}
}

如果只使用部分字母,则不是真正的字谜

在您的例子中,一个好的算法是获取排序后的字符串并逐个字母进行比较,跳过较长单词中的错误匹配。如果到达较短单词的末尾,则有一个匹配项:

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;
  }
}

我可能会采用这种方法来确定一个有序词是否包含另一个有序词的所有字母。请注意,它不会找到真正的字谜(这只是要求两个有序字符串是相同的),但我认为这符合您的要求:

+(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;
}

最简单(但不是最有效)的方法可能是使用
NSCountedSet
。我们可以这样做,因为对于计数集,
[a isSubsetOfSet:b]
当且仅当
[a countForObject:object]删除(有序)草堆中的所有字母,直到并包括针中第一个字符的第一次出现,才返回YES。重复,直到其中一个单词为空?对不起,我不确定我是否理解针/干草堆的比喻。你能说得更具体一点吗?抱歉。直到今天晚上我才有时间给出一个具体的例子,但haystack是你要找的词(较长的词是“eortw”),而needle是你要找的词(你实际上每次只找第一个字母,但说这是“otw”或“ort”),好吧,我认为这是有意义的,我绝对可以试一下。如果你以后有更多的信息,我将非常感激,但是谢谢你,它应该有用!看起来不错。现在要查看Objective-C中StringAfterIndex或getFirstIndex是否以任何形式存在。@lukech我想您可以使用
substringFromIndex:
rangeOfCharacterFromSet:
substringFromIndex:
将起作用,但我需要一种方法来获取该子字符串的第一个实例。我已经修改添加了上面提到的方法。另外,您是否在那里返回方法调用?这是一种递归方法,所以它说“返回使用这些参数调用的函数的值”。我想您可以使用循环,直到其中一个字符串为空。
@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