SQL Server中檢索語句中Like的演算法實現 (轉)
本文主要對字串匹配Like的演算法實現,在 SERVER中Like的匹配中主要有表現為對兩個萬用字元的處理,分別為“_”代表一個字元,“%”代表任意個字元。由於“%”在匹配過程中的位置任意性,所以完全匹配、萬用字元“_”匹配與此不應該一起參與匹配運算,所以我們決定在匹配前先將子串按“%”分段,進行逐段匹配,顯然降低了匹配演算法的難度,下面講解一下演算法的實現過程:(後附實現原始碼)
1. 確定第一個“%”的位置,
目的:確定匹配的方式
a> 是以“%”開頭則不需要左匹配(左匹配即要求子串的第一個字元必須與原串的第一個字元相一致)
b> 不是以“%”開頭則需要進行左匹配
2. 進行KMP*演算法進行模式匹配
KMP演算法不能完全地實現本文提到的匹配演算法,我們必須對此加以修正,主要是模式因子不適合,在這裡必須認為“_”的因子值為與前一個任意字元一致,所以“_”越多,匹配時的回退的可能性將越少,當然其匹配速度比教課書上的模式查詢要快。
3. 繼續下一個子串段的匹配工作。
下面提供演算法的原始碼,分為兩個,
1. _strat
為KMP*模式串查詢函式,函式前有其使用說明。
2. _strlike
為Like的實現過程,內部用到_strat模式串匹配函式,實現的關鍵是對模式串的分段,來降低匹配的難度。
:namespace prefix = o ns = "urn:schemas--com::office" />
////////////////////////////////////////////////////////////////////////////////
// 函式名稱:int _strat(
// char * chText,
// char * chPattern,
// int nbegpos,
// int nlen
// bool bleft )
// 實現功能:模式串搜尋
// 對全域性變數的影響:無
// 引數說明:
// chText 原串
// chPattern 模式串
// nbegpos 起始位置
// nlen 原串相對長度
// bleft 是否左對齊(即第一個字元必須一致)
// 返回結果說明:實際位置
// 待一:回退數不得大於nlen - len(chPattern),即回退後無法導致完全匹配
// 待最佳化二:計算模式串與字串搜尋程式碼合併,減少計算量
////////////////////////////////////////////////////////////////////////////////
int _strat(char * chText , char * chPattern , int nbegp/* = 0 */ , int nlen /* = -1 */ , bool bleft /* = false */)
{
int nPatternLen = _tcslen(chPattern);
int nTextLen = _tcslen(chText);
if(nlen >= 0)
{
if(nbegpos + nlen < nTextLen)
nTextLen = nbegpos + nlen;
}
if(nbegpos + nPatternLen > nTextLen || nPatternLen > MAXLEN_PATTERN)
return -1;
if(nPatternLen == 0)
return nbegpos;
else
{
int nGeneralLen = 0;
short chNext[MAXLEN_PATTERN] = { -1 };
int nPattPos = 0 , nNext = -1;
if(!bleft)
{
//生成模式回退值
while(nPattPos < nPatternLen)
{
if( nNext == -1 || chPattern[nPattPos] == '_' || chPattern[nPattPos] == chPattern[nNext])
{
nPattPos ++;
nNext ++;
chNext[nPattPos] = nNext;
}
else
nNext = chNext[nNext];
}
}
int nTextPos = nbegpos;
nPattPos = 0;
//進行模式匹配
while(nPattPos < nPatternLen && nTextPos < nTextLen)
{
if(nPattPos == -1 || chPattern[nPattPos] == '_' || chPattern[nPattPos] == chText[nTextPos])
{
nPattPos ++;
nTextPos ++;
}
else
{
//要求左對齊時,不允許回退(回退時肯定不是左對齊的)
if(bleft)
return -1;
else
nPattPos = chNext[nPattPos];
}
}
//判斷模式串是否已經完全被匹配,否則返回-1
if(nPattPos == nPatternLen)
return nTextPos - nPattPos;
else
return -1;
}
}
////////////////////////////////////////////////////////////////////////////////
// 函式名稱:bool _strlike(
// char * chText,
// char * chPattern,
// int nbegpos )
// 實現功能:兩個字串的匹配演算法,帶萬用字元
// 對全域性變數的影響:無
// 引數說明:
// chText 原字串
// chPattern 模式串
// nbegpos 起始位置
// 返回結果說明:
// =true 表示相似或一致
// =false 表示不相似或不一致
////////////////////////////////////////////////////////////////////////////////
bool _strlike(char * chText , char * chPattern , int nbegpos /* = 0 */)
{
bool bLeftMatch = true , bLast = false;
int nTextLen = _tcslen(chText);
//作最基礎的匹配,即存在模式串的情況下再作比較
if(_tcslen(chPattern) == 0)
if(_tcslen(chText) == 0)
return true;
else
return false;
do
{
char * chFirstPattern , * chSecondPattern;
if(chPattern[0] == '%')
{
do
{
chPattern ++;
}while(chPattern[0] == '%');
if(chPattern == NULL || _tcslen(chPattern) == 0)
return true;
bLeftMatch = false;
}
else
bLeftMatch = true;
//初始化模式串
chSecondPattern = _tcschr(chPattern , '%');
int nPatternLen;
if(chSecondPattern == NULL)
{
bLast = true;
nPatternLen = _tcslen(chPattern);
if(!bLeftMatch)
{
//若以%開頭,並且沒有剩餘模式串時,只要考慮右對齊匹配的方式即可(實際上也是左對齊)
if(nbegpos + nPatternLen <= nTextLen)
{
nbegpos = nTextLen - nPatternLen;
bLeftMatch = true;
}
else
return false;
}
else
if(nbegpos + nPatternLen != nTextLen)
return false;
}
else
{
//模式串不得長於原串
nPatternLen = chSecondPattern - chPattern;
if(nbegpos + nPatternLen > nTextLen)
return false;
}
//初始化模式串與修改剩餘串
chFirstPattern = new char[nPatternLen + 1];
memcpy(chFirstPattern , chPattern , nPatternLen);
chFirstPattern[nPatternLen] = 0;
chPattern = chSecondPattern;
int npos = _strat(chText , chFirstPattern , nbegpos , bLeftMatch ? nPatternLen : nTextLen - nbegpos , bLeftMatch);
delete chFirstPattern;
if(npos < 0)
{
return false;
}
else
{
//定下一查詢位置的起點
if(bLeftMatch)
{
if(npos != nbegpos)
return false;
}
else
nbegpos = npos;
if(bLast)
{
if(nPatternLen + npos == nTextLen)
return true;
else
return false;
}
else
nbegpos += nPatternLen;
}
}while(true);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-956437/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MyBatis從插入語句中檢索自動生成的IDMyBatis
- sql語句中as的用法SQL
- SQL語句中NULL的真實含義SQLNull
- sql語句中JOIN ON 的使用SQL
- sql語句中#{}和${}的區別SQL
- sql語句中as的用法和作用SQL
- sql語句中select……as的用法SQL
- SQL Server中巧用另類寫法代替Like語句SQLServer
- SQL Server SQL語句中的函式呼叫與Oracle SQL語句函式呼叫一個有趣的差別SQLServer函式Oracle
- SQL語句中exists和in的區別SQL
- SQL語句中not in 和not exist的區別SQL
- sql語句中as的意思是什麼SQL
- 在sql語句中替換Not In 的方法SQL
- sql語句中常量的處理SQL
- SQL Server相似比較演算法實現SQLServer演算法
- SQL Server中檢視SQL句子執行所用的時間SQLServer
- SQL 語句中關於 NULL 的那些坑SQLNull
- 總結SQL語句中的優化提示SQL優化
- MyBatis在SQL語句中取list的大小MyBatisSQL
- 在SQL SERVER中實現RSA加密演算法SQLServer加密演算法
- SQL語句中SELECT語句的執行順序SQL
- MyBatis的使用三(在sql語句中傳值)MyBatisSQL
- SQL Server 實現行列(縱橫表)轉換SQLServer
- SQL Server連線VFP資料庫的實現 (轉)SQLServer資料庫
- SQL Server連線ACCESS資料庫的實現 (轉)SQLServer資料庫
- 怎樣在SQL Server中檢查 IDENTITY 列SQLServerIDE
- 查詢語句中escape的轉義字元字元
- EXCEl中LIKE的實現Excel
- SQL Server之查詢檢索操作SQLServer
- SQL語句中的AND和OR執行順序問題SQL
- Oracle sql 語句中帶有特殊的字元處理OracleSQL字元
- 如何自動填充SQL語句中的公共欄位SQL
- Oracle SQL 語句中正規表示式的應用OracleSQL
- sql語句中較為重要的查詢邏輯SQL
- SQL語句中的單引號與雙引號SQL
- Python 提取出SQL語句中Where的值的方法PythonSQL
- [SQL Server]分頁功能的實現SQLServer
- sql server 中的一些實用的sql語句SQLServer