Skip to content

Commit

Permalink
BM match by Objective-C
Browse files Browse the repository at this point in the history
  • Loading branch information
Smallfly committed Dec 11, 2018
1 parent d4eba0b commit b57ec49
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 2 deletions.
9 changes: 7 additions & 2 deletions java/17_skiplist/SkipList.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,22 @@ public void insert(int value) {
update[i] = head;
}

// record every level largest value which smaller than insert value in update[]
Node p = head;
for (int i = level - 1; i >= 0; --i) {
while (p.forwords[i] != null && p.forwords[i].data < value) {
p = p.forwords[i];
}
update[i] = p;
update[i] = p;// use update save node in search path
}

// in search path node next node become new node forwords(next)
for (int i = 0; i < level; ++i) {
newNode.forwords[i] = update[i].forwords[i];
update[i].forwords[i] = newNode;
}

// update node hight
if (levelCount < level) levelCount = level;
}

Expand All @@ -78,7 +81,8 @@ public void delete(int value) {
}
}

private int randomLevel() {
// 随机 level 次,如果是奇数层数 +1,防止伪随机
private int randomLevel() {
int level = 1;
for (int i = 1; i < MAX_LEVEL; ++i) {
if (r.nextInt() % 2 == 1) {
Expand All @@ -100,6 +104,7 @@ public void printAll() {

public class Node {
private int data = -1;
// 以数组形式维护下一个结点的指针
private Node forwords[] = new Node[MAX_LEVEL];
private int maxLevel = 0;

Expand Down
19 changes: 19 additions & 0 deletions object-c/33_bm_match/BM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// BM.h
// BM-Match
//
// Created by Smallfly on 2018/12/9.
// Copyright © 2018 Smallfly. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface BM : NSObject
- (instancetype)initWithA:(NSString *)a andB:(NSString *)b;
- (NSInteger)startMatch;
- (void)startMatchCompeletion:(void (^)(NSInteger))completion;
@end

NS_ASSUME_NONNULL_END
131 changes: 131 additions & 0 deletions object-c/33_bm_match/BM.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// BM.m
// BM-Match
//
// Created by Smallfly on 2018/12/9.
// Copyright © 2018 Smallfly. All rights reserved.
//

#import "BM.h"

#define SIZE 256

@interface BM()
@property (nonatomic, strong) NSString *a; // 主串
@property (nonatomic, strong) NSString *b; // 匹配串

@property (nonatomic, strong) NSMutableArray *bc; // 匹配串,哈希表,存储字符在匹配串中的下标

@property (nonatomic, strong) NSMutableArray *suffix;
@property (nonatomic, strong) NSMutableArray *prifix;

@end

@implementation BM

- (instancetype)initWithA:(NSString *)a andB:(NSString *)b {
self = [super init];
if (!self) return nil;
_a = a;
_b = b;
_bc = [NSMutableArray new];
_suffix = [NSMutableArray new];
_prifix = [NSMutableArray new];
[self generateBC];
[self generateGS];
return self;
}

// 构建坏字符哈希表,记录每个字符在匹配串中最后出现的位置
- (void)generateBC {
for (int i = 0; i < SIZE; ++i) {
[_bc addObject:@-1];
}
for (int i = 0; i < _b.length; ++i) {
int ascii = (int)[_b characterAtIndex:i]; // char to ASCII
_bc[ascii] = [NSNumber numberWithInteger:i]; // save b's char index
}
}

- (NSInteger)bm {
NSInteger i = 0; // 主串和匹配串对齐的第一个字符
NSUInteger n = _a.length;
NSUInteger m = _b.length;
while (i <= n - m) {
NSInteger j;
// 从后往前匹配
for (j = m - 1; j >= 0; --j) {
int aValue = (int)[_a characterAtIndex:(i + j)];
int bValue = (int)[_b characterAtIndex:j];
if (aValue != bValue) break; // 找到坏字符下标 j 停止
}
if (j < 0) {
return i; // 匹配成功,返回所在的位置
}

// 坏字符在匹配串中最后出现的位置
id numberInHashTableBC = _bc[(int)[_a characterAtIndex:(i + j)]];
NSInteger x = j - [numberInHashTableBC integerValue];
NSInteger y = 0;
if (j < m - 1) {
y = [self moveByGSBy:j];
}
i = i + MAX(x, y);

// 这一步比较难理解,不直接滑到过 j,是因为在 j 之前可能存在于坏字符相同的字符
// 这个于坏字符相同的字符,在匹配串中的最大下标是 numberInHashTableBC
// i = i + (j - [numberInHashTableBC integerValue]);
}

return -1;
}

// 好后缀匹配移动
- (NSInteger)moveByGSBy:(NSInteger)j {
NSUInteger m = _b.length;
NSInteger k = m - 1 - j; // 好后缀的长度
NSInteger t = [_suffix[k] integerValue];
if (t != -1) return j - t + 1; // 匹配串的前缀,是否匹配好后缀,关键
for (NSInteger r = j+1; r <= m-1; ++r) {
if ([_prifix[m-r] boolValue]) { // 关键
return r;
}
}
return m;
}

- (void)generateGS {
NSUInteger m = _b.length;
for (NSInteger i = 0; i < m; ++i) {
_prifix[i] = @(NO);
_suffix[i] = @(-1);
}
for (NSInteger i = 0; i < m - 1; ++i) { // 从 b 中取两个字符对比
NSInteger j = i;
NSInteger k = 0; // 公共后缀的长度
int jValue = (int)[_b characterAtIndex:j];
int bmValue = (int)[_b characterAtIndex:(m-1-k)];
while (j >= 0 && jValue == bmValue) { // 与 b[0, m-1] 求公共子串
++k;
--j;
_suffix[k] = [NSNumber numberWithInteger:(j+1)]; //j+1 代表公共子串在 b 中的起始下标
}
if (j == -1) _prifix[k] = @(YES);
}
}

#pragma mark -

// 同步
- (NSInteger)startMatch {
return [self bm];
}

// 异步
- (void)startMatchCompeletion:(void (^)(NSInteger))completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
completion([self bm]);
});
}

@end
23 changes: 23 additions & 0 deletions object-c/33_bm_match/main.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// main.m
// BM-Match
//
// Created by Smallfly on 2018/12/9.
// Copyright © 2018 Smallfly. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "BM.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
BM *bm = [[BM alloc] initWithA:@"abacadc" andB:@"adc"];

[bm startMatchCompeletion:^(NSInteger index) {
NSLog(@"异步查找到下标:%ld\n", index);
}];

NSLog(@"同步查找到下标:%ld\n", [bm startMatch]);
}
return 0;
}

0 comments on commit b57ec49

Please sign in to comment.