2011-12-21 5 views
20

どのように私はためstrstr()インプレース同等のCに(すなわちないヌルで終了)文字列をカウントしますか?はstrstr()

+3

独自のバージョンを作成する必要があります。 –

+0

どの文字列がNULLで終了していませんか?検索される文字列、またはサブ文字列? –

+0

@TimCooper:検索対象(haystack)です。 – Mehrdad

答えて

5

あなたはO(M * N)行動の恐れている場合 - 基本的に、あなたがする必要はありません、このような場合には、自然に発生しない - ここで私が変更したその周りに私が嘘をついていたKMPの実装があります乾草の長さを取る。またラッパー。繰り返し検索する場合は、自分で作成してborders配列を再利用してください。

バグフリーネスは保証されていませんが、まだ動作しているようです。

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

:ああああ、私は間違いなくこれを試してみよう!ありがとう! :) – Mehrdad

5

以下の機能が機能するかどうかを確認してください。私はそれを徹底的にテストしていないので、そうすることをお勧めします。

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

これは実際に私が現在使っているものと似ていますが、 '' strstr''は '' O(m + n)です。だから私は私のバージョンのように馬鹿げて遅くないものを探しています。 :-)しかし、とにかく、アイデアは動作するので、+1。 – Mehrdad

+0

@Mehrdad:この実装を覗いてみる価値があるかもしれません:http://src.gnu-darwin.org/src/lib/libc/string/strnstr.c.html –

+0

うわー、私は間違っていたと思いますそれで... 'strstr'は通常O(mn)演算であると定義されていますか?それを指摘してくれてありがとう...私は多分これを受け入れるでしょう、なぜならそれは質問のための正確な代案だからです。 – Mehrdad

2

私はちょうどこれに出くわしました、私は私の実装を共有したいと思います。それは私がサブコ​​ールを持っていないことは非常に速いと思う。

針が見つかったhaystackのインデックスを返します。見つからない場合は-1を返します。

/* 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

あなたがそれに行っている間、先に行ってBoyer-Mooreにしてください;) –

関連する問題