이 문자열 검색 알고리즘에서 strlen(검색대상문자열)을 없애려면

cppig1995의 이미지

char *strstr_jump(char *S, const char *s)
{
	char Ereal[256] = {0}, *E = &Ereal[128];
	int i, j, Slen = strlen(S), slen = strlen(s);
	for(i = 0; i < slen; ++i) E[s[i]] = 1;
	for(i = 0; i < Slen; i += slen)
		if(E[S[i]])
			for(j = i - slen + 1; j <= i; ++j)
				if(!strncmp(&S[j], s, slen))
					return &S[j];
	return 0;
}

5625411바이트 중에서 위치 4782202에 있는 10바이트의 문자열을 찾을 때, clock()을 이용해 측정하면 100회 반복에 1300클럭(strstr)-2100클럭(strstr_jump)으로 상당한 차이가 발생합니다. 생각해보니 5625411바이트에 대해 strlen을 돌리니 그 꼴 될 만 하다는 생각이 들었습니다. strlen(S)만 없애면 상당히 개선될 것 같아 보이기도 하더군요.

질문1: strlen(S)를 없애기에는 제 내공이 부족합니다. strlen(S)를 없애려면 어떻게 해야 할까요?
질문2: 최적화할 수 있는 다른 방법은 없을까요?
질문3: 이 문자열 검색 알고리즘을 뭐라고 해야 할까요?

deisys의 이미지

strlen을 쓰는 대신 '\0' 이 나올때까지 iteration 하면 되지 않을까요? 그리고, i가 0일때 j가 음수가 될 수도 있지 않나요? 제대로 따라가보진 않았는데, 얼핏 보니 ...

스트링 검색이면 BM, KMP, Rabin-karp 같은걸 써보시는것도...

s가 좀 길어지면 E 라는 배열을 잡은 의미가 없어질 것 같은데요. strncmp 부분을 최적화하다보면 Rabin-karp 랑 비슷해질것 같습니다.

--
http://www.deisys.net

cppig1995의 이미지

그러게 말입니다.
사실, s 내에 나오는 바이트의 가지수가 100만 넘어도 엄청 느려질 겁니다.
--
임수서룬뫼 윤희수 {cppig1995/돼지군}

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

Hyun의 이미지

char *strstr_jump(char *S, const char *s)
{
    char Ereal[256] = {0}, *E = &Ereal[128];
    int i, j, Slen = strlen(S), slen = strlen(s);
 
    for(i = 0; i < slen; ++i) E[s[i]] = 1;
 
    for(i = 0; i < Slen; i += slen)
        if(E[S[i]])
            for(j = i - slen + 1; j <= i; ++j)
                if(!strncmp(&S[j], s, slen))
                    return &S[j];
 
    return 0;
}
neverdieman의 이미지

char *strstr_jump(char *S, const char *s)
{
char Ereal[256] = {0}, *E = &Ereal[128];
int i, j, Slen = strlen(S), slen = strlen(s);

//이곳에서 플래그만 주지말고 다음 문자값을 가지게하는거에요..
for(i = 0; i < slen; ++i) E[s[i]] = 1;

for(i = 0; i < Slen; i += slen)
if(E[S[i]]) //그리고 이곳에서 비교를 E[S[i]] && E[S[i]] == S[i+1]
//제생각에는 한문자만 일치하는걸로 아래의 반복문을 실행하는건 약간 비효율적이지않을까요?
for(j = i - slen + 1; j <= i; ++j) //방금생각난건데 위에 조건문을 바꾸지말고 이곳 반복문을 E를 가지고 하는거에요
if(!strncmp(&S[j], s, slen)) //이전 문자값을 아는건 인덱스를 아는거고 그럼 추적하다가 원점으로 돌아왔을
return &S[j]; //때 길이가 slen과 같다며 같은문자열이고 원점으로 안온다면 다른문자열이겠죠?
//이방법을 이용할경우엔 위에서 E에 다음 문자값을 가지게하면안되고 이전문자값을
return 0; //가지게해야 좀더 구현이 용이할거같네요
}

제생각 한번써봤는데 이해가 잘안되시면 어쩌죠^^;;
코드로 한번 만들어봐야겠네요~

ㅠㅠ 문단정리 어케하는지 모르겠어영 ㅠㅠ 죄송;

bushi의 이미지

경계검사 때문에 없애기 힘들 것 같습니다.

예외처리 생각하지 않으면

 int l1 = strlen(s1);
 int l2 = strlen(s2);
 
 while (l1 >= l2) {
    if (!memcmp(s1, s2, l2)
        return s1;
    l1--;
    s1++;
 }
 return NULL;

OTL

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.