The most efficient way is to use regex family which is POSIX. Some implementation will build a proper automaton for the patterns. Another way is to repeatedly use KMP or Boyer-Moore search, but you have to scan the string several times, which is less efficient. In addition, what results you want given such input: aa=1, ab=2, bb=3 on string "aabb"?
By the way, when you implement this function, a cleaner solution is to allocate a new dynamic C string and not to modify the original string while replacing. You could implement a in-place replacement, but that would be much more complicated.
regex_t r; regmatch_t match[2]; int last = 0;
regcomp(&r, "(aaa|bbb)", REG_EXTENDED);
insert(hashtable, "aaa", "0"); insert(hashtable, "bbb", "1");
while (regexec(&r, oristr, 1, match, 0) != REG_NOMATCH) {
char *val;
strncat(newstr, oristr + last, match->rm_so);
lookup(hashtable, oristr + match->rm_so, match->rm_eo - match->rm_so, &val);
last = match->rm_eo;
strncat(newstr, val);
}
strcat(newstr, oristr + last);
oristr = realloc(oristr, strlen(newstr));
strcpy(oristr, newstr); free(newstr); regfree(&r);
In practical implementation, you should change the size of newstr dynamically. You should record the end of newstr rather than using strcat/strlen. The source code may be buggy as I have not really tried it. But the idea is there. This is the most efficient implementation I can think of.