Сдвиг всей строки влево на одно место сделает алгоритм O (n ^ 2) эффективным. Вы можете сделать это на месте, в линейное время:
void Remove (char * src, const char * match) {
char * dest = src;
for (;;) {
char ch = *src++;
if (!strchr (match, ch)) *dest++ = ch; // Copy chars that don't match
if (!ch) break; // Stop when we copy over a null
}
}
Я предполагаю, что они обнуляются. Если это не так, то вы также должны передать длины и соответствующим образом изменить алгоритм. В частности, вы не сможете использовать strchr. Просто для полноты, вот версия, которая работает с массивами символов (не завершается нулем).
// Removes from str[] (of length strlen), all chars that are found
// in match[] (of length matchlen). Modifies str in place, and returns
// the updated (shortened) length of str.
int Remove (char[] str, int srclen, char[] match, int matchlen) {
int dst = 0, found;
for (int src = 0; src < srclen; src++) {
char ch = str[src];
found = 0; // Search if this char is found in match
for (int i = 0; i < matchlen && !found; i++)
if (match[i] == ch) found = 1;
if (!found) str[dst++] = ch;
}
return dst;
}
И, наконец, это настолько близко к O (n), насколько мы собираемся получить, я думаю. Я предполагаю, что здесь используются 8-битные символы, и создаю справочную таблицу, поэтому она должна выполняться в O (n) + O (m), где m - длина строки соответствия.
int Remove (char* str, int srclen, char* match, int matchlen) {
bool found[256];
for (int i = 0; i < 256; i++) found[i] = 0;
for (int i = 0; i < matchlen; i++) found[match[i]] = 1;
int dst = 0;
for (int src = 0; src < srclen; src++) {
char ch = str[src];
if (!found[ch]) str[dst++] = ch;
}
return dst;
}