/**
 * Copyright (C) 2013-2017 Vasilis Vryniotis 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.datumbox.framework.core.common.text.analyzers;

import com.datumbox.framework.core.common.utilities.PHPMethods;
import com.datumbox.framework.core.common.text.StringCleaner;
import com.datumbox.framework.core.common.text.extractors.NgramsExtractor;
import com.datumbox.framework.core.common.text.parsers.HTMLParser;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * The TextSimilarity class provides methods that estimate the similarity of two
 * different strings.
 *
 * @author Vasilis Vryniotis 
 */
public class TextSimilarity {
    
    /**
     * This calculates the similarity between two strings as described in Programming 
     * Classics: Implementing the World's Best Algorithms by Oliver (ISBN 0-131-00413-1).
     * 
     * @param text1
     * @param text2
     * @return 
     */
    public static double oliverSimilarity(String text1, String text2) {
        preprocessDocument(text1);
        preprocessDocument(text2);

        String smallerDoc=text1;
        String biggerDoc=text2;
        if(text1.length()>text2.length()) {
            smallerDoc=text2;
            biggerDoc=text1;
        }

        double p=PHPSimilarText.similarityPercentage(smallerDoc, biggerDoc);
        p/=100.0;

        return p;
    }
    
    /**
     * Estimates the w-shingler similarity between two texts. The w is the number
     * of word sequences that are used for the estimation.
     * 
     * References:
     * http://phpir.com/shingling-near-duplicate-detection
     * http://www.std.org/~msm/common/clustering.html
     * 
     * @param text1
     * @param text2
     * @param w
     * @return 
     */
    public static double shinglerSimilarity(String text1, String text2, int w) {
        preprocessDocument(text1);
        preprocessDocument(text2);

        NgramsExtractor.Parameters parameters = new NgramsExtractor.Parameters();
        parameters.setMaxCombinations(w);
        parameters.setMaxDistanceBetweenKwds(0);
        parameters.setExaminationWindowLength(w);

        NgramsExtractor ngrams = new NgramsExtractor(parameters);

        
        Map keywords1 = ngrams.extract(text1);
        Map keywords2 = ngrams.extract(text2);
        
        //remove all the other combinations except of the w-grams
        filterKeywordCombinations(keywords1, w); 
        filterKeywordCombinations(keywords2, w);
        
        //ngrams=null;
        //parameters=null;
        
        double totalKeywords=0.0;
        double commonKeywords=0.0;
        
        Set union = new HashSet<>(keywords1.keySet());
        union.addAll(keywords2.keySet());
        totalKeywords+=union.size();
        //union=null;


        Set intersect = new HashSet<>(keywords1.keySet());
        intersect.retainAll(keywords2.keySet());
        commonKeywords+=intersect.size();
        //intersect=null;
        
        double resemblance=commonKeywords/totalKeywords;

        //keywords1=null;
        //keywords2=null;

        return resemblance;
    }
    
    private static String preprocessDocument(String text) {
        //URLs
        text=StringCleaner.tokenizeURLs(text);

        //Remove HTML
        text=HTMLParser.extractText(text);

        //Remove an Accents
        text=StringCleaner.removeAccents(text);
        
        //Remove extra spaces
        text=StringCleaner.removeExtraSpaces(text);
        
        return text;
    }
    
    private static void filterKeywordCombinations(Map keywords, int w) {
        Iterator> it = keywords.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = it.next();
            if(PHPMethods.substr_count(entry.getKey(), ' ')!=w-1) {
                it.remove();
            }
        }
    }
}
    

 

Ads help maintain this website.