-
[Algorithm]Shift or String matching개발하면서 2010. 11. 21. 18:48반응형
Shift or 알고리즘에 대해 알아보기로 합니다. 명칭부터가 비트 연산으로 비교할 것 같은 느낌이 물씬 나는데요. . .ㅎㅎ;;
알고리즘을 진행하면서 text, pattern 문자열 외에 필요한 변수는 다음과 같습니다.
현재 진행 상태를 나타내는 unsigned long형의 변수
비교할 pattern의 위치를 bit로 표시해줄 unsigned long형의 변수
KMP알고리즘에서도 그랬지만 여기서도 전처리 과정이 필요합니다.
첫번째, 현재 진행 상태를 나타내는 변수, 32개 비트를 0으로 초기화 합니다.
move_bit = ~1;
두번째, 비교할 pattern에서 해당되는 위치는 0, 나머지는 1로 초기화합니다.
for ( i = 0 ~ pattern length ) pattern_mask[i] = ~0; for (i = 0 ~ pattern length ) pattern_mask[pattern[i]] &= ~(1UL << i );
text = kana k kasdf kang han asdfkang han gooxvxcva
pattern = kang han goo
을 예로 들어 설명하겠습니다.
전처리 후에 준비된 변수는 다음과 같습니다.
move_bit = 0000 0000 0000 0000 0000 0000 0000 0000pattern_mask['k'] = 1111 1111 1111 1111 1111 1111 1111 1110
pattern_mask['a'] = 1111 1111 1111 1111 1111 1111 1011 1101
pattern_mask['n'] = 1111 1111 1111 1111 1111 1111 0111 1011
pattern_mask['g'] = 1111 1111 1111 1111 1111 1101 1111 0111
pattern_mask['h'] = 1111 1111 1111 1111 1111 1111 1101 1111
pattern_mask['n'] = 1111 1111 1111 1111 1111 1111 1111 1111
pattern_mask['o'] = 1111 1111 1111 1111 1111 0011 1111 1111
pattern_mask[' '] = 1111 1111 1111 1111 1111 1110 1110 1111
순서도는 아래와 같습니다
pattern의 길이가 m, text길이가 n이라 할 때
전처리 : O(m+ n )
문자열 처리 O(mn) 의 복잡도를 가집니다.
#include <stdio.h> #include <string.h> #include <limits.h> const int LIMIT_TAB=20; void bit_print(char *buf, unsigned long bit); const char *bitap_bitwise_search(const char *text, const char *pattern) { int m = strlen(pattern); unsigned long move_bit; unsigned long pattern_mask[CHAR_MAX+1]; int i; #ifdef _DEBUG char buf[50]; #endif if (pattern[0] == '\0') return text; if (m > 31) return "The pattern is too long!"; /* Initialize the bit array R */ move_bit = ~1; #ifdef _DEBUG printf("goal is move_bit & (1UL<<m) equal 0\n"); #endif /* Initialize the pattern bitmasks */ for (i=0; i <= CHAR_MAX; ++i) pattern_mask[i] = ~0; for (i=0; i < m; ++i) pattern_mask[pattern[i]] &= ~(1UL << i); for (i=0; text[i] != '\0'; ++i) { /* Update the bit array */ #ifdef _DEBUG bit_print("move_bit", move_bit); sprintf(buf, "pattern_mask[%c]", text[i]); bit_print(buf, pattern_mask[text[i]]); #endif move_bit |= pattern_mask[text[i]]; move_bit <<= 1; if (0 == (move_bit & (1UL << m))) return (text + i - m) + 1; } return NULL; } int main() { char *pattern = "kang han goo"; char * text = "kana k kasdf kang han asdfkang han gooxvxcva"; const char *find; unsigned long t = 32; find = bitap_bitwise_search(text, pattern); printf("find : %s\n", find); //bit_print("sample", t); return 0; } void bit_print(char *buf, unsigned long bit) { int i; int buf_len; unsigned long mask; mask = (1UL <<31 ); buf_len = strlen(buf); for ( i = 0; i < (LIMIT_TAB - buf_len); i++ ) { printf(" "); } printf("%s : ", buf); for ( i = 0; i < 32; i++ ) { if (i%4 == 0) { printf(" "); } printf("%d", (bit & mask) >> (31-i)); mask >>= 1; } printf("\n"); }
출처 : http://en.wikipedia.org/wiki/Bitap_algorithm
ps. 마지막에 개선된것같은데 이것도 한번 들여다봐야겠습니다.
반응형