- //by baihacker
- #include <iostream>
- #include <vector>
- #include <functional>
- #include <algorithm>
- using namespace std;
- template<typename FType, typename SType>
- struct equal_cmp
- {
- bool operator ()(const FType& _F, const SType& _S)const
- {return _F == _S;}
- };
- template<typename RandAccessConcept,
- typename EqualCmp>
- inline void
- CalFailFunction(
- const RandAccessConcept& in,
- int len,
- vector<int>& ff,
- EqualCmp cmp
- )
- {
- ff.clear();
- ff.reserve(len);
- ff.push_back(-1);
- for (int curr = 1, k = -1; curr < len; ++curr)
- {
- for (;k >= 0 && !cmp(in[k+1], in[curr]);
- k = ff[k]);
- if (cmp(in[k+1], in[curr])) ++k;
- ff.push_back(k);
- }
- }
- template<typename FRandAccessConcept,
- typename SRandAccessConcept,
- typename EqualCmp>
- inline int
- KMPSearchFirst(
- const FRandAccessConcept& d,
- int dlength,
- const SRandAccessConcept& p,
- int plength,
- EqualCmp cmp,
- int start = 0
- )
- {
- vector<int> ff;
- CalFailFunction(p, plength, ff, cmp);
- for (int i = start, j = -1; i < dlength; ++i)
- {
- while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j];
- if (cmp(d[i], p[j+1])) ++j;
- if (j == plength - 1) return i - plength + 1;
- }
- return -1;
- }
- template<typename FRandAccessConcept,
- typename SRandAccessConcept,
- typename EqualCmp>
- inline int
- KMPSearchALL(
- const FRandAccessConcept& d,
- int dlength,
- const SRandAccessConcept& p,
- int plength,
- vector<int>& result,
- EqualCmp cmp
- )
- {
- vector<int> ff;
- CalFailFunction(p, plength, ff, cmp);
- result.clear();
- for (int i = 0, j = -1; i < dlength; ++i)
- {
- while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j];
- if (cmp(d[i], p[j+1])) ++j;
- if (j == plength - 1)
- {
- result.push_back(i - plength + 1);
- j = ff[j];
- }
- }
- return result.size();
- }
- int main()
- {
- int d[] = {1,2,3,1,2,3,1,2};
- char p[] = "/1/2/3/1/2";
- vector<int> result;
- int found = KMPSearchALL(d, 8, p, 5, result, equal_cmp<int, char>());
- for (int i = 0; i < found; ++i)
- cout << result[i] << " ";
- cout << endl;
- return 0;
- }
2013/06/29 : 更新一些能直接使用并用于较短模式串的代码。推荐一本叫《柔性字符串匹配》的书
template<typename ElemType>
int MatchSO(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
typedef unsigned long long NumberType;
const int CharSet = 128;
NumberTypeB[CharSet];
NumberTypeD = ~0;
NumberTypeCheck = 1 << (m-1);
NumberTypeBIT = 1;
for (int i = 0; i < CharSet; ++i) B[i] = ~0;
for (int i = 0; i < m; ++i, BIT <<= 1) B[p[i]] &= ~BIT;
result.clear();
for (int i = 0; i < n; ++i)
{
D = (D << 1) | B[t[i]];
if ((D & Check) == 0) result.push_back(i-m+1);
}
return result.size();
}
template<typename ElemType>
int MatchSA(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
typedef unsigned long long NumberType;
const int CharSet = 128;
NumberTypeB[CharSet];
NumberTypeD = 0;
NumberTypeCheck = 1 << (m-1);
NumberTypeBIT = 1;
for (int i = 0; i < CharSet; ++i) B[i] = 0;
for (int i = 0; i < m; ++i, BIT <<= 1) B[p[i]] |= BIT;
result.clear();
for (int i = 0; i < n; ++i)
{
D = ((D << 1) | 1) & B[t[i]];
if ((D & Check) != 0) result.push_back(i-m+1);
}
return result.size();
}
template<typename ElemType>
int MatchKMP(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
int* Prefix = new int[m];
{
Prefix[0] = -1;
for (int i = 1, F = -1; i < m; ++i)
{
while (F >= 0 && p[F+1] != p[i]) F = Prefix[F];
if (p[F+1] == p[i]) ++F;
Prefix[i] = F;
}
}
{
result.clear();
for (int i = 0, F = -1; i < n; ++i)
{
while (F >= 0 && p[F+1] != t[i]) F = Prefix[F];
if (p[F+1] == t[i]) ++F;
if (F+1 == m)
{
result.push_back(i-m+1);
F = Prefix[F];
}
}
}
delete[] Prefix;
return result.size();
}