2011-12-21 30 views
20

Làm thế nào để làm tại chỗ tương đương với strstr() cho một tính chuỗi (ví dụ: không null-terminated) trong C?strstr() cho một chuỗi đó là KHÔNG null-chấm dứt

+3

Bạn sẽ phải viết phiên bản của riêng mình. –

+0

Chuỗi nào không được kết thúc bằng null? Chuỗi được tìm kiếm hoặc chuỗi con? –

+0

@TimCooper: Cái đang được tìm kiếm (haystack). – Mehrdad

Trả lời

5

Nếu bạn sợ O (m * n) hành vi - về cơ bản, bạn cần không, trường hợp này không xảy ra một cách tự nhiên - đây là một thực hiện KMP tôi đã nằm xung quanh mà tôi đã sửa đổi để lấy chiều dài của đống cỏ khô. Ngoài ra một wrapper. Nếu bạn muốn thực hiện các tìm kiếm lặp lại, hãy tự viết và sử dụng lại mảng borders.

Không đảm bảo cho lỗi-freeness, nhưng dường như vẫn hoạt động.

int *kmp_borders(char *needle, size_t nlen){ 
    if (!needle) return NULL; 
    int i, j, *borders = malloc((nlen+1)*sizeof(*borders)); 
    if (!borders) return NULL; 
    i = 0; 
    j = -1; 
    borders[i] = j; 
    while((size_t)i < nlen){ 
     while(j >= 0 && needle[i] != needle[j]){ 
      j = borders[j]; 
     } 
     ++i; 
     ++j; 
     borders[i] = j; 
    } 
    return borders; 
} 

char *kmp_search(char *haystack, size_t haylen, char *needle, size_t nlen, int *borders){ 
    size_t max_index = haylen-nlen, i = 0, j = 0; 
    while(i <= max_index){ 
     while(j < nlen && *haystack && needle[j] == *haystack){ 
      ++j; 
      ++haystack; 
     } 
     if (j == nlen){ 
      return haystack-nlen; 
     } 
     if (!(*haystack)){ 
      return NULL; 
     } 
     if (j == 0){ 
      ++haystack; 
      ++i; 
     } else { 
      do{ 
       i += j - (size_t)borders[j]; 
       j = borders[j]; 
      }while(j > 0 && needle[j] != *haystack); 
     } 
    } 
    return NULL; 
} 

char *sstrnstr(char *haystack, char *needle, size_t haylen){ 
    if (!haystack || !needle){ 
     return NULL; 
    } 
    size_t nlen = strlen(needle); 
    if (haylen < nlen){ 
     return NULL; 
    } 
    int *borders = kmp_borders(needle, nlen); 
    if (!borders){ 
     return NULL; 
    } 
    char *match = kmp_search(haystack, haylen, needle, nlen, borders); 
    free(borders); 
    return match; 
} 
+0

: O Ồ wow, tôi chắc chắn sẽ thử điều này! Cảm ơn! :) – Mehrdad

5

Kiểm tra xem chức năng dưới đây có phù hợp với bạn hay không. Tôi đã không thử nghiệm nó kỹ lưỡng, vì vậy tôi sẽ đề nghị bạn làm như vậy.

char *sstrstr(char *haystack, char *needle, size_t length) 
{ 
    size_t needle_length = strlen(needle); 
    size_t i; 

    for (i = 0; i < length; i++) 
    { 
     if (i + needle_length > length) 
     { 
      return NULL; 
     } 

     if (strncmp(&haystack[i], needle, needle_length) == 0) 
     { 
      return &haystack[i]; 
     } 
    } 
    return NULL; 
} 
+0

Đó là thực sự tương tự như những gì tôi đang sử dụng, nhưng nó là O (mn), trong khi (tôi giả sử) 'strstr' là O (m + n). Vì vậy, tôi đang tìm kiếm một cái gì đó không ridiculously chậm như phiên bản của tôi. :-) Nhưng dù sao đi nữa, vì ý tưởng hoạt động. – Mehrdad

+0

@Mehrdad: Cũng có thể đáng để xem qua việc triển khai này: http://src.gnu-darwin.org/src/lib/libc/string/strnstr.c.html –

+0

Chà, tôi đoán mình đã sai sau đó ... vì vậy 'strstr' thường được định nghĩa là một hoạt động O (mn) ?? Cảm ơn bạn đã chỉ ra rằng ... sau đó tôi có thể sẽ chấp nhận điều này trong một chút, vì nó là sự thay thế chính xác cho câu hỏi. – Mehrdad

2

Tôi vừa mới xem xét điều này và tôi muốn chia sẻ triển khai của mình. Nó nghĩ rằng nó khá nhanh, tôi không có bất kỳ subcalls.

Nó trả về chỉ mục trong haystack nơi kim được tìm thấy hoặc -1 nếu không tìm thấy.

/* binary search in memory */ 
int memsearch(const char *hay, int haysize, const char *needle, int needlesize) { 
    int haypos, needlepos; 
    haysize -= needlesize; 
    for (haypos = 0; haypos <= haysize; haypos++) { 
     for (needlepos = 0; needlepos < needlesize; needlepos++) { 
      if (hay[haypos + needlepos] != needle[needlepos]) { 
       // Next character in haystack. 
       break; 
      } 
     } 
     if (needlepos == needlesize) { 
      return haypos; 
     } 
    } 
    return -1; 
} 
+1

Nên đi trước và làm cho nó Boyer-Moore trong khi bạn đang ở đó;) –

Các vấn đề liên quan