字符串匹配
性質
給定模式集合,和源集合。
算法輸出源集合中和模式匹配的所有相關處的起始位置。
接口設計
template<typename T>
class CharacterMatch
{
public:
CharacterMatch();
~CharacterMatch();
public:
DataStruct::Array::DynArray<int> RunInAutoMachine(
const DataStruct::Array::DynArray<T>& arrPattern_,
const DataStruct::Array::DynArray<T>& arrSource_);
};
實現
構造
template<typename T>
CharacterMatch<T>::CharacterMatch()
{
}
析構
template<typename T>
CharacterMatch<T>::~CharacterMatch()
{
}
算法運行
template<typename T>
DataStruct::Array::DynArray<int> CharacterMatch<T>::RunInAutoMachine(
const DataStruct::Array::DynArray<T>& arrPattern_,
const DataStruct::Array::DynArray<T>& arrSource_)
{
int _nPatternLen = arrPattern_.GetSize();
int _nSourceLen = arrSource_.GetSize();
int _nPreMaxMatchLen = 0;
int _nCurMaxMatchLen = 0;
DataStruct::Array::DynArray<int> _arrRet;
for (int _i = 0; _i < _nSourceLen; _i++)
{
if (_nPreMaxMatchLen == _nPatternLen)
{
for (int _nCurMayMaxMatchLen = _nPreMaxMatchLen; _nCurMayMaxMatchLen >= 0; _nCurMayMaxMatchLen--)
{
bool _bSuccess = true;
int _k = 0;
while (_k < _nCurMayMaxMatchLen)
{
if (arrSource_[_i - _k] == arrPattern_[_nCurMayMaxMatchLen - 1 - _k])
{
_k++;
}
else
{
break;
}
}
if (_k == _nCurMayMaxMatchLen)
{
_bSuccess = true;
}
else
{
_bSuccess = false;
}
if (_bSuccess)
{
_nCurMaxMatchLen = _nCurMayMaxMatchLen;
break;
}
}
}
else
{
if (arrSource_[_i] == arrPattern_[_nPreMaxMatchLen])
{
_nCurMaxMatchLen = _nPreMaxMatchLen + 1;
}
else
{
for (int _nCurMayMaxMatchLen = _nPreMaxMatchLen; _nCurMayMaxMatchLen >= 0; _nCurMayMaxMatchLen--)
{
bool _bSuccess = true;
int _k = 0;
while (_k < _nCurMayMaxMatchLen)
{
if (arrSource_[_i - _k] == arrPattern_[_nCurMayMaxMatchLen - 1 - _k])
{
_k++;
}
else
{
break;
}
}
if (_k == _nCurMayMaxMatchLen)
{
_bSuccess = true;
}
else
{
_bSuccess = false;
}
if (_bSuccess)
{
_nCurMaxMatchLen = _nCurMayMaxMatchLen;
break;
}
}
}
}
if (_nCurMaxMatchLen == _nPatternLen)
{
_arrRet.Add(_i - _nPatternLen + 1);
}
_nPreMaxMatchLen = _nCurMaxMatchLen;
}
}
算法目標&正確性證明
算法正確性證明:
算法以迭代方式實現
以迭代方式實現的算法正確性證明依賴於循環不變式
循環不變式:
每次迭代開始時,我們總是可以得到到上次迭代位置爲止,可以與模式產生的最大匹配的長度
若循環不變式成立,
可知,我們在每次迭代結束,得到本次迭代位置爲止,可以與模式產生的最大匹配的長度
若該長度 等於 模式本身長度,則 得到的一次模式的匹配。
如此,必可得到 所有關於模式的匹配信息。得證。
循環不變式證明:
初始時,
在首次迭代前,_nPreMaxMatchLen = 0,循環不變式成立。
對於第k次迭代,
依據循環不變式,_nPreMaxMatchLen表示到上次位置爲止可以與模式產生的最大匹配的長度
若
本位置元素 等於 模式第(_nPreMaxMatchLen+1)處元素
易於知道,此時
從當前位置往前共(_nPreMaxMatchLen+1)個元素,分別依次與模式第(_nPreMaxMatchLen+1)到第一個元素依次相等。
故,當前位置位置 可與模式達成的最大匹配長度必然 >= (_nPreMaxMatchLen+1)
假設 當前位置位置 可與模式達成的最大匹配長度 爲len > (_nPreMaxMatchLen+1)
則,可推導出 當前上一位置爲止 可與模式達成的最大匹配長度 必然 >= (len-1) > _nPreMaxMatchLen
這與事實矛盾,故當前位置位置 可與模式達成的最大匹配長度爲 (_nPreMaxMatchLen+1)
若
本位置元素 不等於 模式第(_nPreMaxMatchLen+1)處元素
假設當前位置位置 可與模式達成的最大匹配長度 爲len > (_nPreMaxMatchLen+1)
則,可推導出 當前上一位置爲止 可與模式達成的最大匹配長度 必然 >= (len-1) > _nPreMaxMatchLen
這與事實矛盾,故當前位置位置 可與模式達成的最大匹配長度不會大於 (_nPreMaxMatchLen+1)
假設當前位置位置 可與模式達成的最大匹配長度 爲len = (_nPreMaxMatchLen+1)
則,可推導出 本位置元素 等於 模式第(_nPreMaxMatchLen+1)處元素,
這與事實矛盾,故當前位置位置 可與模式達成的最大匹配長度不會等於 (_nPreMaxMatchLen+1)
綜合,當前位置位置 可與模式達成的最大匹配長度只會<= (_nPreMaxMatchLen)
而我們對_nPreMaxMatchLen,...,0可能的匹配長度依次進行考察
故,考察完畢必可得到正確的_nCurMaxMatchLen
綜合,一次迭代結束,我們總是能得到 當前位置爲止可能與模式產生的最大匹配的長度,
進而,循環不變式成立。