BM 算法 Cpp 实现

介绍

BM 算法在文本模式匹配方面的效率不用多说,在 linux 上文件搜索上的使用也证明了它的实用价值,这有一篇它的原理介绍, BM算法介绍

Show you the code
#include <algorithm>
#include <iostream>
#include "BM.h"


#define  FS_MATCH_NOCASE
#ifdef FS_MATCH_NOCASE
#define bm_tolower(c) \
    if(c >= BDS_TEXT('A') && c <= BDS_TEXT('Z')) c+= 32;
#else
#define  bm_tolower(c)
#endif

namespace BaiduService
{
namespace FileSearch
{


CMBMMatch::CBMMatch::CBMMatch() :
           m_pattern(NULL),
           m_arraySuffixTable(NULL),
           m_nPatternLen(0)
{
    m_pArrayBadCharTable = (char *)malloc(1 << 16);
    memset(m_pArrayBadCharTable, -1, 1 << 16);
}


CMBMMatch::CBMMatch::~CBMMatch()
{
    if (m_arraySuffixTable)
    {
        free(m_arraySuffixTable);
    }

    if (m_pattern != NULL)
    {
        free(m_pattern);
    }

    if (m_pArrayBadCharTable != NULL)
    {
        free(m_pArrayBadCharTable);
    }
}


bool CMBMMatch::CBMMatch::SetPattern(const BDS_TCHAR *pattern)
{

    // bad char table
    m_nPatternLen  = bdststrlen(pattern);
    if (m_nPatternLen < 1)
    {
        return false;
    }

    if (m_pattern != NULL)
    {
        free(m_pattern);
    }

    m_pattern = (BDS_TCHAR *)malloc((m_nPatternLen + 1) * sizeof(BDS_TCHAR));
    memset(m_pattern, 0, (m_nPatternLen + 1) * sizeof(BDS_TCHAR));
#ifndef FS_MATCH_NOCASE 
    bdsstrcpy(m_pattern, pattern);
#else // 


    for (size_t i = 0; i < m_nPatternLen; i++)
    {
        BDS_TCHAR c = pattern[i];
        bm_tolower( c );
        m_pattern[i] = c;
    }
#endif



    for (size_t i = 0; i < m_nPatternLen; i++)
    {
        m_pArrayBadCharTable[(USHORT)m_pattern[i]] = i;
    }


    // build good suffix table, from right to left
    m_arraySuffixTable = (char *)malloc(m_nPatternLen);

    char cLastGoodSuffix = 1;
    for (size_t i = m_nPatternLen - 1; i > 0; i--)
    {
        // compare the prefix
        size_t j = 0;
        for (; j < m_nPatternLen - i; j++)
        {
            if ( m_pattern[j] != m_pattern[j + i] )
            {
                break;
            }
        }

        if (j == m_nPatternLen - i)
        {
            m_arraySuffixTable[i] = i;
            cLastGoodSuffix = i;
        }
        else
        {
            m_arraySuffixTable[i] = cLastGoodSuffix;
        }

    }

    // ajust the last subffix
    m_arraySuffixTable[0] = cLastGoodSuffix;
    m_arraySuffixTable[m_nPatternLen - 1] = 1;


    // find the good suffix
    for (size_t i = m_nPatternLen - 1; i > 0; i--)
    {

        int nLocation = 0;
        nLocation = FindSubString( &m_pattern[i], &m_pattern[0] );

        if (nLocation != 0)
        {
            m_arraySuffixTable[i-1] = i - nLocation;
        }

    }

    return true;
}


bool CMBMMatch::CBMMatch::Match(const BDS_TCHAR *text)
{
    // do search
    bool bFound = false;
    size_t nTextLen = bdststrlen(text);
    if (nTextLen < m_nPatternLen)
    {
        return false;
    }

    size_t i = 0;
    for ( ; i < nTextLen;)
    {
        int j = m_nPatternLen - 1;
        for ( ; j >= 0; j--)
        {
            if (i + j > nTextLen - 1)
            {
                return false;
            }

            BDS_TCHAR c = text[i + j];
            bm_tolower(c);
            if (m_pattern[j] != c )
            {
                // find the next jump
                if ((j - m_pArrayBadCharTable[(USHORT)c]) > m_arraySuffixTable[j])
                {
                    i += (j - m_pArrayBadCharTable[(USHORT)c]);
                }
                else
                {
                    i += m_arraySuffixTable[j];
                }

                break;
            }
        }

        if (j == -1)
        {
            bFound = true;
            break;
        }
    }

    return bFound;

}


int CMBMMatch::CBMMatch::FindSubString(const BDS_TCHAR *szPattern, const BDS_TCHAR *szText)
{
    int nLocation = 0;
    int nLastLocation = 0;
    size_t nTextLen = bdststrlen( szText );
    size_t nPatternLen = bdststrlen( szPattern );
    for (size_t i = 0; i < nTextLen; i++)
    {
        size_t j = 0;
        for ( ; j < nPatternLen; j++ )
        {
            if ( szPattern[j] != szText[i + j] )
            {
                break;
            }
        }

        if ( j == nPatternLen )
        {
            nLastLocation = nLocation;
            nLocation = i;
        }
    }

    return nLastLocation;
}


CMBMMatch::CMBMMatch()
{

}


CMBMMatch::~CMBMMatch()
{
    Reset();
}


bool CMBMMatch::Reset()
{
    std::for_each(m_vecMatch.begin(), m_vecMatch.end(), [&](CBMMatch *match) {

         delete match;

    });

    m_vecMatch.clear();
    m_vecPatterns.clear();

    return true;
}


bool CMBMMatch::SetPatterns(std::vector<bdststring> vecPatterns)
{
    Reset();

    m_vecPatterns = vecPatterns;

    std::for_each(m_vecPatterns.begin(), m_vecPatterns.end(), [&](bdststring pattern) {

         CBMMatch *match = new CBMMatch();

         if (match->SetPattern(pattern.c_str()))
         {
             m_vecMatch.push_back(match);
         }
         else
         {
             delete match;
         }
    });

    return true;
}


bool CMBMMatch::Match(const BDS_TCHAR *text)
{
    bool bFound = true;

    //bFound = m_vecMatch[0]->Match(text);

    std::all_of(m_vecMatch.begin(), m_vecMatch.end(), [&](CBMMatch *match) -> bool {
        if (!match->Match(text))
        {
            bFound = false;
            return false;
        }

        return true;
    });

    return bFound;
}


}
}

介绍没有经过优化以及详细 review,写好之后就没有再看了,难免有问题,可以自行处理。

在OpenCV中,BM(Block Matching)算法是用于计算视差图的一种方法。BM算法的参数包括以下几个: 1. blockSize:块大小,表示在计算视差时使用的像素块的大小。通常情况下,较小的块大小能提供更精细的视差图,但计算速度更慢。默认值为21。 2. numDisparities:视差搜索范围,表示在计算视差时搜索的范围。该值必须是16的倍数,并且通常设置为大于块大小的值。默认值为64。 3. preFilterType:预处理滤波器类型,表示在计算视差之前使用的预处理滤波器类型。可选的值有0(预处理滤波器未使用)和1(预处理滤波器使用WTA_HARRIS滤波器)。默认值为1。 4. preFilterSize:预处理滤波器大小,表示在计算视差之前使用的预处理滤波器的大小。默认值为5。 5. preFilterCap:预处理滤波器截断值,表示在计算视差之前使用的预处理滤波器的截断值。默认值为31。 6. textureThreshold:纹理阈值,表示在计算视差时用于判断像素块是否具有足够纹理信息的阈值。默认值为10。 7. uniquenessRatio:唯一性比率,表示在计算视差时用于判断像素块的视差是否唯一的比率。默认值为15。 8. speckleWindowSize:相干窗口大小,表示在计算视差时用于去除孤立噪声的相干窗口的大小。默认值为100。 9. speckleRange:相干范围,表示在计算视差时用于去除孤立噪声的相干范围。默认值为32。 这些参数可以通过创建一个BM对象并使用其成员函数setXXX来设置。例如,可以使用以下代码设置块大小和视差搜索范围: ```cpp cv::StereoBM bm; bm.setBlockSize(11); bm.setNumDisparities(64); ``` 请注意,这里只提到了一些常用的参数,实际上还有其他参数可供调整以获得更好的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值