116 lines
2.9 KiB
C++
116 lines
2.9 KiB
C++
|
/**
|
|||
|
* @file -
|
|||
|
* @author jingqi
|
|||
|
* @date 2012-10-18
|
|||
|
* @last-edit 2012-11-13 21:36:50 jingqi
|
|||
|
* @ref https://blog.csdn.net/jingqi_se/article/details/14055709
|
|||
|
*/
|
|||
|
|
|||
|
#ifndef ___HEADFILE_A04A7FB7_1516_4EF0_A8B9_44C5AABBF7EC_
|
|||
|
#define ___HEADFILE_A04A7FB7_1516_4EF0_A8B9_44C5AABBF7EC_
|
|||
|
|
|||
|
#include <assert.h>
|
|||
|
#include <string>
|
|||
|
|
|||
|
namespace nut
|
|||
|
{
|
|||
|
|
|||
|
/**
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>KMP<EFBFBD>Զ<EFBFBD>״̬<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|||
|
*
|
|||
|
* @param target <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ len <EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
|
|||
|
* @param next <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ len <EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD>KMP<EFBFBD>Զ<EFBFBD>״̬<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|||
|
*/
|
|||
|
inline void kmp_build_next(const char *target, int *next, size_t len)
|
|||
|
{
|
|||
|
assert(NULL != target && NULL != next && len > 0);
|
|||
|
if (len > 0)
|
|||
|
next[0] = 0;
|
|||
|
size_t i = 1;
|
|||
|
int state = 0;
|
|||
|
while (i < len)
|
|||
|
{
|
|||
|
if (target[i] == target[state])
|
|||
|
next[i++] = ++state;
|
|||
|
else if (0 == state)
|
|||
|
next[i++] = 0;
|
|||
|
else
|
|||
|
state = next[state - 1];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>KMP״̬
|
|||
|
*
|
|||
|
* @param c <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
|
|||
|
* @param state <EFBFBD><EFBFBD>ǰ״̬
|
|||
|
* @param target Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
|
|||
|
* @param next KMP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* @return <EFBFBD>µ<EFBFBD>״̬
|
|||
|
*/
|
|||
|
inline int kmp_update(char c, int state, const char *target, const int *next)
|
|||
|
{
|
|||
|
assert(state >= 0 && NULL != target && NULL != next);
|
|||
|
while (true)
|
|||
|
{
|
|||
|
if (c == target[state])
|
|||
|
return ++state;
|
|||
|
else if (0 == state)
|
|||
|
return 0;
|
|||
|
else
|
|||
|
state = next[state - 1];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* KMP<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* @param src <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* @param start <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
|
|||
|
* @param target Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
|
|||
|
* @param next KMP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>target<EFBFBD><EFBFBD>ͬ)
|
|||
|
*/
|
|||
|
inline int kmp_search(const char *src, size_t len_src, size_t start, const char *target, const int *next, size_t len_target)
|
|||
|
{
|
|||
|
assert(NULL != src && NULL != target && NULL != next);
|
|||
|
size_t i = start;
|
|||
|
int state = 0; // ״̬<D7B4><CCAC><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
while (i < len_src && ((size_t) state) < len_target)
|
|||
|
state = kmp_update(src[i++], state, target, next);
|
|||
|
if (state == (int)len_target)
|
|||
|
return i - len_target;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* KMP<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KMP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>类<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬλ<EFBFBD>ã<EFBFBD>
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>(<EFBFBD>μ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>)
|
|||
|
*
|
|||
|
* @param src <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* @param start <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
|
|||
|
* @param target Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
|
|||
|
*/
|
|||
|
inline int kmp_search(const std::string& src, size_t start, const std::string& target)
|
|||
|
{
|
|||
|
int *next = new int[target.length()];
|
|||
|
kmp_build_next(target.c_str(), next, target.length());
|
|||
|
const int ret = kmp_search(src.c_str(), src.length(), start, target.c_str(), next, target.length());
|
|||
|
delete[] next;
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
inline int kmp_search(const char *src, size_t len_src, const char *target, size_t len_target)
|
|||
|
{
|
|||
|
int *next = new int[len_target];
|
|||
|
kmp_build_next(target, next, len_target);
|
|||
|
const int ret = kmp_search(src, len_src, 0, target, next, len_target);
|
|||
|
delete[] next;
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endif
|