void AssemblyJobSsDeBruijn::findBestLinks(DeBruijnGraph* graph){
  char nucs[] = {'A','T','C','G'};
  for (DeBruijnGraph::Iterator nodeIt = graph->begin(); nodeIt != graph->end(); ++nodeIt){
    DeBruijnNode* currentNode = *nodeIt;
    DeBruijnNode* best5pLink = 0;
    float best5pLinkScore = 0;
    DeBruijnNode* best3pLink = 0;
    float best3pLinkScore = 0;
    for (int n = 0; n < 4; ++n){
      DeBruijnNode* cand5pLink = currentNode->get5pLink(nucs[n]);
      if (cand5pLink != 0){
	// take the worse of the two linkage scores
	float next5pLinkScore;
	if (currentNode->get5pLinkScore(nucs[n]) > cand5pLink->get3pLinkScore(currentNode->get3pNuc()) ){
	  next5pLinkScore = cand5pLink->get3pLinkScore(currentNode->get3pNuc());
	} else { next5pLinkScore = currentNode->get5pLinkScore(nucs[n]); }
	if (next5pLinkScore > best5pLinkScore){
	  best5pLinkScore = next5pLinkScore;
	  best5pLink = cand5pLink;
	}
      }
      DeBruijnNode* cand3pLink = currentNode->get3pLink(nucs[n]);
      if (cand3pLink != 0){
	// take the worse of the two linkage scores
	float next3pLinkScore;
	if (currentNode->get3pLinkScore(nucs[n]) > cand3pLink->get5pLinkScore(currentNode->get5pNuc()) ){
	  next3pLinkScore = cand3pLink->get5pLinkScore(currentNode->get5pNuc());
	} else { next3pLinkScore = currentNode->get3pLinkScore(nucs[n]); }
	if (next3pLinkScore > best3pLinkScore){
	  best3pLinkScore = next3pLinkScore;
	  best3pLink = cand3pLink;
	}
      }
    }
    currentNode->setBest5pLink(best5pLink);
    currentNode->setBest3pLink(best3pLink);
  }

  // FOURTH resolve best-edge conflicts
  for (DeBruijnGraph::Iterator nodeIt = graph->begin(); nodeIt != graph->end(); ++nodeIt){
    DeBruijnNode* currentNode = *nodeIt;
    DeBruijnNode* best5pLink = currentNode->best5pLink();
    if (best5pLink != 0 and best5pLink->best3pLink() != currentNode){
      DeBruijnNode* bestRecip = best5pLink->best3pLink();
      if (bestRecip == 0){ best5pLink->setBest3pLink(currentNode); }
      else { currentNode->setBest5pLink( 0 ); }
    }
    DeBruijnNode* best3pLink = currentNode->best3pLink();
    if (best3pLink != 0 and best3pLink->best5pLink() != currentNode){
      DeBruijnNode* bestRecip = best3pLink->best5pLink();
      if (bestRecip == 0){ best3pLink->setBest5pLink(currentNode); }
      else { currentNode->setBest3pLink( 0 ); }
    }
  }
}
ScoredSeq* AssemblyJobSsDeBruijn::makeSeqFromPath(DeBruijnNode* node5p, DeBruijnNode* node3p, long numNodes){
  long seqLen = _kmerSize + numNodes - 1;
  char* cSeq = new char[seqLen + 1];
  cSeq[seqLen] = '\0';
  float* scores = new float[seqLen];
  float* links = new float[seqLen-1];

  // do the initial kmer and any overlapping positions
  node5p->getKmer(cSeq,0);
  float firstScore = node5p->getKmerScore();
  for (int n = 0; n < _kmerSize; ++n){
    scores[n] = firstScore;
    if (n < _kmerSize - 1){ links[n] = firstScore; }
  }

  // fill in the rest
  DeBruijnNode* currentNode = node5p;
  DeBruijnNode* priorNode = 0;
  long pos5p = 0;
  long pos3p = _kmerSize - 1;
  while (currentNode != node3p){
    // increment
    pos5p++;
    pos3p++;
    priorNode = currentNode;
    currentNode = currentNode->best3pLink();
    // fill in values
    cSeq[pos3p] = currentNode->get3pNuc();
    scores[pos3p] = currentNode->getKmerScore();
    links[pos3p-1] = priorNode->get3pLinkScore( currentNode->get3pNuc() );
    if (links[pos5p-1] < currentNode->get5pLinkScore( cSeq[pos5p-1] )){
      links[pos5p-1] = currentNode->get5pLinkScore( cSeq[pos5p-1] );
    }
    for (long pos = pos5p; pos < pos3p; ++pos){
      if (scores[pos] < currentNode->getKmerScore()){ scores[pos] = currentNode->getKmerScore(); }
    }
  }

  ScoredSeq* novelSeq = new ScoredSeqShallow(true, cSeq, scores, links, seqLen);
  //ScoredSeq* novelSeq = ScoredSeq::getScoredSeq(cSeq, scores, links, seqLen);
  /*
  delete [] cSeq;
  delete [] scores;
  delete [] links;
  */
  return novelSeq;
}