Showing the minimum of letters needed for a palindrome This shows the minimum of letters needed for a palindrome.  It needs tweaking since it works fine for words 1-9 characters, but becomes slow for words with 10-12 characters, and for 13+ characters it really takes a lot of time. Any help is appreciated.

#include &lt;stdio.h&gt;
#include &lt;conio.h&gt;
#include &lt;string.h&gt;
#include &lt;malloc.h&gt;

typedef struct _el {
    char ch;
    struct _el* next;
} lst;

typedef struct _lst {
    char* string;
    struct _lst* next;
} elmt;

char* _remove(char*, int);
int min(int , int);
elmt* _ncptr(char [], int, elmt*, int );
int minfinal(char [], int, int );
elmt* _add(elmt* root, elmt* elm);
int _count(elmt* root);
int _last_p(elmt* root);
int ispnd(char [], int);
int __exist (elmt* root, char* str, int h);
int max(int, int);
lst* add(lst* root, char n);
int exist(lst* root, char n);

int main() {
    int l, min;
    char b[50];
    printf("Insert the word:");
    scanf("%s", b);
    l = strlen(b) - 1;
         printf("%d letters needed.\n", minfinal(b, 0, l));
    _getch();
    return 0;             
}

int min(int a, int b) {
    return ((a&gt;b) ? b : a);
}

elmt* _ncptr(char v[], int quant, elmt* root, int count) {
    int cnt_, lvar;
    int len = strlen(v)-1;
    if(!root) {
        root = (elmt*)malloc(sizeof(elmt));
        root-&gt;string = (char*)malloc(len+1);
        strcpy(root-&gt;string, v);
        root-&gt;next = '\0';
    }
    if(quant == 0) return root;
    if(count &gt; 0) {
        int i;
        elmt *n_el, *tmp = root;
        i = 0;
        while(i &lt; count) {
            int j;
            j = 0;  
            for(j = 0; j &lt; strlen(tmp-&gt;string); j++) {
                n_el = (elmt*)malloc(sizeof(elmt));
                n_el-&gt;string = _remove(tmp-&gt;string, j);
                n_el-&gt;next = '\0';

                if(__exist(root, n_el-&gt;string, i+j+1)) continue;
                root = _add(root, n_el);
            }
            tmp = tmp-&gt;next;
            i++;
        }
        return( _ncptr( v, quant-1, root, _count(root)-count ) );
    }
    else {
        //MAYBE IT's FIRST CALL OF THE FUNCTION
        int i,j;
        elmt* n_el;
        i = strlen(v);
        for(j = 0; j &lt; i; j++) {
            n_el = (elmt*)malloc(sizeof(elmt));
                n_el-&gt;string = _remove(v, j);
                n_el-&gt;next = '\0';
                root = _add(root, n_el);
        }
        return( _ncptr( v, quant-1, root, _count(root) ) );
    }
}

char* _remove(char* str, int i) {
    int j,k;
    char* nstr = (char*)malloc(strlen(str));
    nstr[0] = '\0';
    for(j = 0, k = 0; j &lt; strlen(str); j++) {
        if(j == i) { continue; }

        nstr[k] = str[j];
        k++;
    }
    nstr[k] = '\0';
    return nstr;
}

elmt* _add(elmt* root, elmt* elm) {
    elm-&gt;next = root;
    return elm;
}

int _count(elmt* root) {
    long int l_var;
    for( l_var = 0; root &amp;&amp; root-&gt;string; l_var++, root=root-&gt;next );
    return l_var;
}

int minfinal(char v[], int n, int i) {
    elmt* g = NULL;
    if(ispnd(v, i)) return 0;

    g = _ncptr(v, i, g, 0);

    return( strlen(v) - _last_p(g) );
}

int ispnd(char v[], int z) {
    int i, j, k;
    k = 0;
    for(i = 0, j = z; i &lt; j; i++, j--) {
        if(v[i] != v[j]) {
            k = 1;
            break;
        }
    }
    return !k;
}

int _last_p(elmt* root) {
    int l_var = 0;
    for(; root; root=root-&gt;next ) {
          if(strlen(root-&gt;string) == 0) continue;
        if(!ispnd(root-&gt;string, strlen(root-&gt;string)-1)) continue;
        l_var = max( l_var, strlen(root-&gt;string) );
    }
    return l_var;
}

int __exist (elmt* lstt, char* str, int h) {
    int i,j;
    for(j=0; lstt, j &lt;= h; lstt = lstt-&gt;next, j++ ) {
        i = strcmp(lstt-&gt;string, str);

        if(!i) return 1;        
    }
    return 0;
}

int max(int a, int b) {
    return (a &gt; b ? a : b );
}
This is an obvious candidate: (there are more lines containing this anti-pattern):

for(j = 0, k = 0; j &lt; strlen(str); j++) {...}


Will result in the strlen being called on every iteration, nmaking the whole thing an O(N*N) operation.

A better way to do the same would be:

size_t len,j,k;

len = strlen(str);
for (j=k=0; j &lt; len;j++) {...}


Next:

char* _remove(char*, int);
elmt* _ncptr(char [], int, elmt*, int );
elmt* _add(elmt* root, elmt* elm);
int _count(elmt* root);
int _last_p(elmt* root);
int __exist (elmt* root, char* str, int h);


Identifiers with leading underscores are reserved for the implementation and / or the library. 

In short: don't use them (unless you are implementing the implemnetation or the library, but in that case you would not ask this question, methinks)

Next: the _remove function is terrible. I malloc() one byte too short, calls strlen() at every heartbeat, and ignores the existing string functions.

char *newremove(char *org, size_t pos) {
    size_t len;
    char *new;

    len =  strlen(org) 
    new = malloc(1+len);

    if (pos &lt; len) {
      memcpy(new, org, pos);
      memcpy(new+pos,org+pos+1, len-pos);
      }

    else {
      memcpy(new, org, len+1);
      }

return new;


}