我有一个算法可以在一组八个字母的单词中找到字谜。实际上,它会对较长单词中的字母进行字母顺序排列,逐个对较短的单词执行相同操作,并查看它们是否存在于较长的单词中,如下所示:
tower = eortw
two = otw
rot = ort
这里的问题是,如果我在ort
中寻找eortw
(或在塔中腐烂),它会找到它,没问题。在塔内发现腐烂。但是,otw
不在eortw
内(或塔中的两个),因为中间有R.因此,它不认为塔中有两个。
我有更好的方法吗?我正在尝试在Objective-C中执行此操作,并且八个字母的单词和常规单词都存储在NSDictionaries
中(使用其正常和按字母顺序排列的形式)。
我看过其他各种帖子了。 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);
}
}
}
答案 0 :(得分: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;
}
}
答案 1 :(得分:0)
这是我可能采取的一种方法,用于查明一个有序单词是否包含另一个有序单词的所有字母。请注意,它不会找到真正的字谜(这只需要两个有序的字符串是相同的)但这符合我认为你要求的:
+(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;
}
答案 2 :(得分:0)
最简单(但不是最有效)的方式可能是使用NSCountedSet
。我们可以这样做,因为对于计数集,[a isSubsetOfSet:b]
当且仅当[a countForObject:object] <= [b countForObject:object]
为object
中的a
时返回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