#include <iostream.h>
#include <string.h>

class AArray {

        // maintains a set S of strings and a function f(s) -> integer

public:

        // if (s not \in S) add s to S
        // return reference to f(s)
        int & operator [] (const char *s);

        // if (s \in S) return 0; else return 1;
        int present (const char *s);

        AArray();
        virtual ~AArray();

private:

	// maintains a linked list

	// single element in list
	struct Elem {
		char *_str;
		int   _v;
		Elem *_next;
	};

	// header
	Elem *_elem;

	// internal find, returns element if there
	Elem *find(const char*s);

	// print it out
        friend ostream & operator <<
                ( ostream & Out, const AArray & Value );

};

// start off with a null list
AArray::AArray() {
	_elem = NULL;
}

// delete all elements in list
AArray::~AArray() {
	Elem *p,*q;
	p  = _elem;
	while ( p != NULL ) {
		q = p->_next;
		delete [] p->_str;	
		delete p;
		p = q;
	}
}

// run through list looking for s;
AArray::Elem *AArray::find(const char*s) {
	Elem *p=_elem;
	while ( p != NULL ) {
		if(strcmp(s,p->_str)==0) return p;
		p = p->_next;
	}
	return NULL;
}	

// if we can find it, it's there
int AArray::present(const char*s) {
	return (find(s)==NULL)?0:1;
}

// get reference to f(s)
int & AArray::operator [] (const char *s) {

	// find s
	Elem *p=find(s);
	
	if(p==NULL) {
		// if s is not in S, add it
		p = new Elem;
		p->_str = new char[strlen(s)+1];
		strcpy  (p->_str,s);
		p->_v   = 0;
		p->_next= _elem;
		_elem   = p;
	}
	return p->_v;
}

// print it out
ostream & operator << ( ostream & Out, const AArray & Value ) {
        AArray::Elem *p=Value._elem;
        while ( p != NULL ) {
                Out << p->_str << " " << p->_v << "\n";
                p = p->_next;
        }
        return Out;
}

// trivial use example
int main()
{
	AArray a;

	a["hello"]++;
	cout 	<< a["hello"]++ 
		<< " " 
		<< a["goodbye"]++ 
		<< " " 
		<< a["hello"] 
		<< " " 
		<< a["goodbye"]
		<< "\n";

	cout 	<< a;

	return 0;
}
