1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-10 16:14:40 +02:00

* Moved levenshtein method to TomahawkUtils.

This commit is contained in:
Christian Muehlhaeuser
2012-06-27 05:21:22 +02:00
parent 23f47f82a6
commit d7d8c5940f
4 changed files with 89 additions and 89 deletions

View File

@@ -498,13 +498,13 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
{
// result values
const QString rArtistname = r->artist()->sortname();
const QString rAlbumname = DatabaseImpl::sortname( r->album()->name() );
const QString rAlbumname = r->album()->sortname();
const QString rTrackname = DatabaseImpl::sortname( r->track() );
// normal edit distance
int artdist = levenshtein( m_artistSortname, rArtistname );
int albdist = levenshtein( m_albumSortname, rAlbumname );
int trkdist = levenshtein( m_trackSortname, rTrackname );
int artdist = TomahawkUtils::levenshtein( m_artistSortname, rArtistname );
int albdist = TomahawkUtils::levenshtein( m_albumSortname, rAlbumname );
int trkdist = TomahawkUtils::levenshtein( m_trackSortname, rTrackname );
// max length of name
int mlart = qMax( m_artistSortname.length(), rArtistname.length() );
@@ -521,7 +521,7 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
const QString artistTrackname = DatabaseImpl::sortname( fullTextQuery() );
const QString rArtistTrackname = DatabaseImpl::sortname( r->artist()->name() + " " + r->track() );
int atrdist = levenshtein( artistTrackname, rArtistTrackname );
int atrdist = TomahawkUtils::levenshtein( artistTrackname, rArtistTrackname );
int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
float dcatr = (float)( mlatr - atrdist ) / mlatr;
@@ -922,83 +922,3 @@ Query::infoSystemFinished( QString target )
emit updated();
}
int
Query::levenshtein( const QString& source, const QString& target )
{
// Step 1
const int n = source.length();
const int m = target.length();
if ( n == 0 )
return m;
if ( m == 0 )
return n;
// Good form to declare a TYPEDEF
typedef QVector< QVector<int> > Tmatrix;
Tmatrix matrix;
matrix.resize( n + 1 );
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
// allow for allocation on declaration of 2.nd dimension of vec of vec
for ( int i = 0; i <= n; i++ )
{
QVector<int> tmp;
tmp.resize( m + 1 );
matrix.insert( i, tmp );
}
// Step 2
for ( int i = 0; i <= n; i++ )
matrix[i][0] = i;
for ( int j = 0; j <= m; j++ )
matrix[0][j] = j;
// Step 3
for ( int i = 1; i <= n; i++ )
{
const QChar s_i = source[i - 1];
// Step 4
for ( int j = 1; j <= m; j++ )
{
const QChar t_j = target[j - 1];
// Step 5
int cost;
if ( s_i == t_j )
cost = 0;
else
cost = 1;
// Step 6
const int above = matrix[i - 1][j];
const int left = matrix[i][j - 1];
const int diag = matrix[i - 1][j - 1];
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
if ( above + 1 < cell )
cell = above + 1;
// Step 6A: Cover transposition, in addition to deletion,
// insertion and substitution. This step is taken from:
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
// Enhanced Dynamic Programming ASM Algorithm"
// (http://www.acm.org/~hlb/publications/asm/asm.html)
if ( i > 2 && j > 2 )
{
int trans = matrix[i - 2][j - 2] + 1;
if ( source[ i - 2 ] != t_j ) trans++;
if ( s_i != target[ j - 2 ] ) trans++;
if ( cell > trans ) cell = trans;
}
matrix[i][j] = cell;
}
}
// Step 7
return matrix[n][m];
}

View File

@@ -97,7 +97,7 @@ public:
QID id() const;
/// sorter for list of results
static bool resultSorter( const result_ptr &left, const result_ptr& right );
static bool resultSorter( const result_ptr& left, const result_ptr& right );
/// true when a perfect result has been found (score of 1.0)
bool solved() const { return m_solved; }
@@ -221,7 +221,6 @@ private:
void checkResults();
void updateSortNames();
static int levenshtein( const QString& source, const QString& target );
void parseSocialActions();

View File

@@ -329,13 +329,93 @@ void
msleep( unsigned int ms )
{
#ifdef WIN32
Sleep( ms );
Sleep( ms );
#else
::usleep( ms * 1000 );
#endif
}
int
levenshtein( const QString& source, const QString& target )
{
// Step 1
const int n = source.length();
const int m = target.length();
if ( n == 0 )
return m;
if ( m == 0 )
return n;
// Good form to declare a TYPEDEF
typedef QVector< QVector<int> > Tmatrix;
Tmatrix matrix;
matrix.resize( n + 1 );
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
// allow for allocation on declaration of 2.nd dimension of vec of vec
for ( int i = 0; i <= n; i++ )
{
QVector<int> tmp;
tmp.resize( m + 1 );
matrix.insert( i, tmp );
}
// Step 2
for ( int i = 0; i <= n; i++ )
matrix[i][0] = i;
for ( int j = 0; j <= m; j++ )
matrix[0][j] = j;
// Step 3
for ( int i = 1; i <= n; i++ )
{
const QChar s_i = source[i - 1];
// Step 4
for ( int j = 1; j <= m; j++ )
{
const QChar t_j = target[j - 1];
// Step 5
int cost;
if ( s_i == t_j )
cost = 0;
else
cost = 1;
// Step 6
const int above = matrix[i - 1][j];
const int left = matrix[i][j - 1];
const int diag = matrix[i - 1][j - 1];
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
if ( above + 1 < cell )
cell = above + 1;
// Step 6A: Cover transposition, in addition to deletion,
// insertion and substitution. This step is taken from:
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
// Enhanced Dynamic Programming ASM Algorithm"
// (http://www.acm.org/~hlb/publications/asm/asm.html)
if ( i > 2 && j > 2 )
{
int trans = matrix[i - 2][j - 2] + 1;
if ( source[ i - 2 ] != t_j ) trans++;
if ( s_i != target[ j - 2 ] ) trans++;
if ( cell > trans ) cell = trans;
}
matrix[i][j] = cell;
}
}
// Step 7
return matrix[n][m];
}
static QMutex s_noProxyHostsMutex;
static QStringList s_noProxyHosts;

View File

@@ -100,9 +100,10 @@ namespace TomahawkUtils
DLLEXPORT QString ageToString( const QDateTime& time, bool appendAgoString = false );
DLLEXPORT QString filesizeToString( unsigned int size );
DLLEXPORT QString extensionToMimetype( const QString& extension );
DLLEXPORT void msleep( unsigned int ms );
DLLEXPORT bool newerVersion( const QString& oldVersion, const QString& newVersion );
DLLEXPORT int levenshtein( const QString& source, const QString& target );
DLLEXPORT NetworkProxyFactory* proxyFactory( bool makeClone = false, bool noMutexLocker = false );
DLLEXPORT void setProxyFactory( TomahawkUtils::NetworkProxyFactory* factory, bool noMutexLocker = false );