public String explainScore(StringWrapper s, StringWrapper t) {
	String S = s.unwrap(),
	  T = t.unwrap();
    StringBuffer buff = new StringBuffer();
    buff.append("\n****TagLinkToken****\n");
    buff.append("Si=" + S + ", Tj=" + T + "\n");
    double totalScore = 0.0;
    if (S.equals(T)) {
      matched = S.length();
      buff.append("Sij=1.0");
    }
    else {
      sSize = S.length();
      tSize = T.length();
      // let S be the biggest token
      if (sSize < tSize) {
        String tmp1 = S;
        S = T;
        T = tmp1;
        double tmp2 = sSize;
        sSize = tSize;
        tSize = tmp2;
      }
      ArrayList candidateList = algorithm1(S, T);
      sortList(candidateList);
      buff.append("Common characteres:\n");
      buff.append("Si\tTj\tScore_ij(Si,Tj)\n");
      matched = 0;
      HashMap tMap = new HashMap(),
          uMap = new HashMap();
      java.util.Iterator it = candidateList.iterator();
      while (it.hasNext()) {
        TagLink.Candidates actualCandidates = (TagLink.Candidates) it.next();
        Integer sPos = new Integer(actualCandidates.getTPos()),
            tPos = new Integer(actualCandidates.getUPos());
        if ( (!tMap.containsKey(sPos)) &&
            (!uMap.containsKey(tPos))) {
          double actualScore = actualCandidates.getScore();
          totalScore += actualScore;
          tMap.put(sPos, null);
          uMap.put(tPos, null);
          buff.append(S.charAt(sPos.intValue()) + "\t" + T.charAt(tPos.intValue()) +
                      "\t" + round(actualScore) + "\n");
          matched++;
        }
      }
      totalScore = (totalScore / ( (double) sSize) + totalScore / ( (double) tSize)) / 2.0;
      System.out.println("score " + totalScore);
      buff.append("Score_ij(S,T)=" + round(winkler(totalScore, S, T)));
      buff.append("\nMatched characters=" + matched);
    }
    return buff.toString();
  }