#include <stdio.h>

/* insert your own values */
typedef unsigned int NODE;
#define ROOT_NODE 1
#define M_LETTER 0xff
#define V_LETTER 24
#define M_END_OF_NODE 1
#define M_END_OF_WORD 2
#define M_NODE_POINTER 0xfffffc
#define V_NODE_POINTER 2

typedef struct {
  int len;
  NODE *edge;
} TItem;

TItem item[32];

#define LET(a) (((a)>>V_LETTER)&M_LETTER)
#define PTR(a) (((a)>>V_NODE_POINTER)&M_NODE_POINTER)
#define DAWG(a) (dawg+(a))

static int nstr;
static NODE *dawg;

unsigned char reslengths[32];

int init()
{
  nstr=0;
  /* do your initing here */
  return(0);
}

int uninit()
{
  /* do your uniniting here */
  return(0);
}

/* take the char and return the number of lengths returned in reslengths[] */
int process_one_char(unsigned char c)
{ int rl,i; NODE *edge;
  rl=0;
  /* append a root node as last item */
  item[nstr].edge=dawg+ROOT_NODE;
  item[nstr++].len=0;
  for(i=0;i<nstr;i++) { NODE w;
    /* ignore invalid items */
    while(item[i].edge==dawg) {
      if(--nstr==i) break;
      item[i].edge=item[nstr].edge;
      item[i].len=item[nstr].len;      
    }
    if(nstr==i) break;
    /* start processing valid item */
    edge=item[i].edge;
    do {
      w=*edge;
      /* check letter at the edge */
      if(LET(w)==c) {
        item[i].len++;
        /* if string matched insert its length to result array */
        if(w&M_END_OF_WORD) reslengths[rl++]=item[i].len;
        /* go through edge, will be ignored at next char if invalid */
        item[i].edge=DAWG(PTR(w));
        break;
      }
      /* next edge if char didn't match */
      edge++;
    } while((w&M_END_OF_NODE)==0);
  }
  return(rl);
}

int main(int argc, char **argv)
{ int c; FILE *fin;
  if(argc<2) {
    fprintf(stderr,"Usage: mscan filename\n");
    exit(1);
  }
  init();
  if(fin=fopen(argv[1],"rb")) {
    while((c=getc(fin))!=EOF) {
      process_one_char(c);
    }
    fclose(fin);
  }
  uninit();
  return(0);
}