字符匹配算法
❶ 字符串匹配的传统算法
传统的匹配算法
串匹配算法虽然发展了几十年,然而非常实用的算法是近年才出现。串匹配问题的研究存在理论研究和实际应用的脱节。那些专门从事算法研究的学者关心的只是理论上看起来很美妙的算法——具有很好的时间复杂度。而开发人员只追求实际应用中尽可能快的算法。两者之间从不注意对方在干什么。将理论研究和实际应用结合的算法(如BNDM算法)只是近年才出现。在实际应用中常常很难找到适合需求的算法——这样的算法实际上是存在的,但是只有资深专家才比较了解。考虑如下情况,一位软件开发人员,或者一位计算生物学家,或者一位研究人员,又或者一位学生,对字符串匹配领域并没有深入了解,可是现在需要处理一个文本搜索问题。那些汗牛充栋的书籍使得阅读者淹没在各种匹配算法的海洋中,却没有足够的知识选择最适用的算法。最后,常常导致这样的局面:选择一种最简单的算法加以实现。这往往导致很差的性能,从而影响整个开发系统的质量。更糟糕的是,选择了一个理论上看起来很漂亮的算法,并且花费了大量精力去实现。结果,却发现实际效果和一个简单算法差不多,甚至还不如简单算法。因此,应该选用一种“实用”算法,即在实际应用中性能较好,并且一个普通程序员能在几小时内完成算法的实现代码。另外,在字符串匹配研究领域中,一个人所共知的事实是“算法的思想越简单,实际应用的效果越好”。
传统的串匹配算法可以概括为前缀搜索、后缀搜索、子串搜索。代表算法有KMP,Shift-And,Shift-Or,BM,Horspool,BNDM,BOM等。所用到的技术包括滑动窗口、位并行、自动机、后缀树等。
❷ 关于一个字符串匹配算法
我看了一下代码的,大概觉得它主要实现的功能是查找*y对应字符串中是否有与*x对应的字符串相等的子字符串存在,如果存在则返回该子串第一个字符在*y中的位置。
但是你没有把问题说清楚,比如preBmBc和memcmp这两个函数是在你给的程序中没有定义的,我猜了好久都不能猜出他们确切的用途。我估计你们老师主要也是叫你们实现这两个函数吧。。
如果你能在把问题给得详细的。。我可以继续帮你想想。。
不愧是毕业设计的题目啊,确实有点难度啊。我觉得那个函数不是一个简单的字符串匹配算法,它是一个多重字符串匹配算法。我给你个C语言的例子你参考一下吧。一下两下我也搞不出来了,真不好意思。
boyermoore算法的sample程序
TCHAR * BoyerMooreSearch(TCHAR *sSrc, TCHAR *sFind)
{
//
// 声明:
// 该段代码只是BoyerMoore(名字也许不准确)的基本思想,当
// 然不是最优的,具体完善工作就留给你自己乐!嘻嘻。
// 该算法的本质就是从字符串的右端而不是左端开始比较,这
// 样,当查询不匹配时才有可能直接跃过多个字符(最多可以跃过
// strlen(sFind)个字符),如果最右边的字符匹配则回溯。比如:
//
// pain
// ^ 这是第一次比较n和空格比
// The rain in SpainThe rain in Spain
//
// pain
// ^ 这是第二次比较,好爽呀!
// The rain in SpainThe rain in Spain
//
// 当然,这样比较会产生一些问题,比如:
//
// pain
// ^ (图1)
// The rain in SpainThe rain in Spain
//
// 如果比较到这儿,大家都会看到,只需再向后移到两个字符
// 就匹配成功了,但如果接下去还按上面的方法跳strlen(sFind)的
// 话,就会错过一次匹配!!!!!
//
// pain
// ^
// The rain in SpainThe rain in Spain
//
// 怎么办?当然可以解决!大家回头看图1,当时a是pain的子
// 串,说明有可能在不移动strlen(sFind)的跨度就匹配成功,那就
// 人为地给它匹配成功的机会嘛!串一下pain串,直接让两个a对齐
// 再做比较!呵呵,如果要比较的字符不是pain的子串,当然就可
// 以直接跨过strlen(sFind)个字符了!不知我说明白没?
//
//
// 查询串的长度
int nLenOfFind = lstrlen(sFind);
// 被查询串的长度
int nLenOfSrc = lstrlen(sSrc);
// 指向查询串最后一个字符的指针
TCHAR * pEndOfFind = sFind + nLenOfFind -1;
// 指向被查询串最后一个字符的指针
TCHAR * pEndOfSrc = sSrc + nLenOfSrc -1;
// 在比较过程中要用到的两个指针
TCHAR * pSrc = sSrc;
TCHAR * pFind;
// 总不能一直让它比较到win.com文件的地址去吧?嘻嘻!
while ( pSrc <= pEndOfSrc ) {
// 每次匹配都是从右向左,这是本算法的核心。
pFind = pEndOfFind;
// 如果比较不成功,被查询串指针将向右串的字符数
int nMoveRightSrc;
// 比较被查询串的当前字符是否和查询串的最右边字
// 符匹配,如果匹配则回溯比较,如果全匹配了,该
// 干什么,我就不用说了吧?:-)
while ( pFind >= sFind ) {
// TNND,白废功夫比了!看看需要向右移动几个
// 字符吧(如果说从右到左是本算法的核心,则
// 判断向右移几个字符则是本算法的技巧)。
if ( *pSrc != *pFind ) {
// 被查询串的当前字符是否在查询串里?
TCHAR * p = strrchr( sFind, *pSrc );
// 没在,直接移lstrlen(sFind)个字符
if ( NULL == p )
nMoveRightSrc = nLenOfFind;
else
// 哇塞!真的在,那就只需...
nMoveRightSrc = pEndOfFind - p;
break;
}
// 哈!又匹配成功了一个!接着向左回溯...
pFind --;
pSrc --;
}
// 如果在上面的while循环里每一次比较都匹配了
// 那就对了呗!告诉用户找到了
if ( pFind < sFind )
return ( pSrc + 1 );
// 没匹配成功,nMoveRightSrc上面已经算好了
// 直接用就可以了。
pSrc += nMoveRightSrc;
}
// 程序运行到这儿肯定是没指望了!
return NULL;
}
行了,函数写完了,我们可以试一下了!
void CTNNDDlg::OnButton1()
{
TCHAR sSrc[] = "The rain in Spain";
TCHAR sFind[]= "pain";
TCHAR * pFound = BoyerMooreSearch( sSrc, sFind );
if ( pFound )
MessageBox(pFound);
else
MessageBox("没找到");
}
//另外一个
void preBmBc(char *x, int m, int bmBc[]) {
int i;
for (i = 0; i < ASIZE; ++i)
bmBc[i] = m;
for (i = 0; i < m - 1; ++i)
bmBc[x[i]] = m - i - 1;
}
void suffixes(char *x, int m, int *suff) {
int f, g, i;
suff[m - 1] = m;
g = m - 1;
for (i = m - 2; i >= 0; --i) {
if (i > g && suff[i + m - 1 - f] < i - g)
suff[i] = suff[i + m - 1 - f];
else {
if (i < g)
g = i;
f = i;
while (g >= 0 && x[g] == x[g + m - 1 - f])
--g;
suff[i] = f - g;
}
}
}
void preBmGs(char *x, int m, int bmGs[]) {
int i, j, suff[XSIZE];
suffixes(x, m, suff);
for (i = 0; i < m; ++i)
bmGs[i] = m;
j = 0;
for (i = m - 1; i >= -1; --i)
if (i == -1 || suff[i] == i + 1)
for (; j < m - 1 - i; ++j)
if (bmGs[j] == m)
bmGs[j] = m - 1 - i;
for (i = 0; i <= m - 2; ++i)
bmGs[m - 1 - suff[i]] = m - 1 - i;
}
void BM(char *x, int m, char *y, int n) {
int i, j, bmGs[XSIZE], bmBc[ASIZE];
/* Preprocessing */
preBmGs(x, m, bmGs);
preBmBc(x, m, bmBc);
/* Searching */
j = 0;
while (j <= n - m) {
for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i);
if (i < 0) {
OUTPUT(j);
j += bmGs[0];
}
else
j += MAX(bmGs[i], bmBc[y[i + j]] - m + 1 + i);
}
}
❸ 想找一个解决两个字符串匹配程度的算法。
假设string1="abcde",string2="bcd",则分析逻辑如下:
1. 如果string2长于string1,则不匹配
2. 在string1中顺序查匹配string2中第一个字符的字符,
查到后,如果string1余下的字符串长度小于string2的长度,则不匹配
3. 在上述条件满足时,将string1的下一个字符和string2中的第二个字符匹配,以此类推,一旦有一个不匹配,则不匹配。回到第2步,查找下一个和string2首字符一致的字符。
4. 如果string2中的字符全都匹配上,则说明string2中string1中识别出来了。
❹ 字符串匹配算法的基本思想是什么
这个用到了正规表达式对字符串的匹配.程序如下,是javascript的.
<script language="javascript">
function check(obj)
{var str=/^[0-9]{4}-[0-9]{7}$/ig;
if(str.test(obj))
alert("this is your number");
else
alert("write again");}
</script>
<form name="form1">
<input type="text" name="mytext" size="12">
<input type="button" value="click" onclick="check
(form1.mytext.value)">
</form>
要求输入的是标准电话号码.看不懂问我.呵呵.
❺ 什么是字符串多模式匹配和字符串多模式匹配算法又如何
你问两个多模式匹配有什么区别吗..
多模式就是说查找的子串不止一个.
你可以当做是单一模式匹配的叠加版,那样直接套KMP也行.
至于字典树(trie),一般用于英文单词匹配.
trie是一棵树,树上的每一条边都是一个字母,除了根节点之外的每一个节点都代表一个单词.
对于每一个节点,都有26个指针:指针A - 指针Z,分别对应26个字母
一开始时,字典树只有一个根节点,当加入一个单词时,先向根节点插入一个元素,连接根节点的一个指针,这个指针编号是单词的第一个字母,然后再在这个新的节点上增加一个元素,指针编号是第二个字母...以此类推.
检索过程很简单,自己想想就懂了,这个结构已经十分好理解了.
❻ 开源的字符串匹配算法有哪些
匹配整个字符串: /^javascript$/ 匹配包含: /javascript/ 匹配整个建议用==或者indexOf,(即不需要使用正则表达式) 正则表达式的优点在于模式匹配, 缺点是它的性能远比普通的字符串查找低下
❼ 最容易理解,容易学的的字符串匹配算法
最简单的是暴力匹配 叫什么我忘了 就是双重for循环 复杂度是n1*n2
其次是Sunday算法 具体过程自己搜吧 也不难 算是剑走偏锋的 而且它的速度一般是最快的 复杂度 n1+n2
然后是kmp算法 纯论速度它还不如Sunday 算法 而且也比较难理解 但是它对于后面的一些其他的学习是有必要的 复杂度 n1+n2
❽ 字符串匹配算法是怎么算的
这是一个毕业老师出的字符串的算法的题目!这是答案 可以参考一下! boyermoore算法的sample程序 TCHAR * BoyerMooreSearch(TCHAR *sSrc, TCHAR *sFind) { // // 声明: // 该段代码只是BoyerMoore(名字也许不准确) 的基本思想,当 // 然不是最优的,具体完善工作就留给你自己乐!嘻嘻。 // 该算法的本质就是从字符串的右端而不是左端开始比较,这 // 样,当查询不匹配时才有可能直接跃过多个字符(最多可以跃过 // strlen(sFind)个字符), 如果最右边的字符匹配则回溯。比如: // // pain // ^ 这是第一次比较n和空格比 // The rain in SpainThe rain in Spain // // pain // ^ 这是第二次比较,好爽呀! // The rain in SpainThe rain in Spain // // 当然,这样比较会产生一些问题,比如: // // pain // ^ (图1) // The rain in SpainThe rain in Spain // // 如果比较到这儿,大家都会看到,只需再向后移到两个字符 // 就匹配成功了,但如果接下去还按上面的方法跳strlen( sFind)的 // 话,就会错过一次匹配!!!!! // // pain // ^ // The rain in SpainThe rain in Spain // // 怎么办?当然可以解决!大家回头看图1,当时a是pain的子 // 串,说明有可能在不移动strlen(sFind) 的跨度就匹配成功,那就 // 人为地给它匹配成功的机会嘛!串一下pain串, 直接让两个a对齐 // 再做比较!呵呵,如果要比较的字符不是pain的子串,当然就可 // 以直接跨过strlen(sFind)个字符了! 不知我说明白没? // // // 查询串的长度 int nLenOfFind = lstrlen(sFind); // 被查询串的长度 int nLenOfSrc = lstrlen(sSrc); // 指向查询串最后一个字符的指针 TCHAR * pEndOfFind = sFind + nLenOfFind -1; // 指向被查询串最后一个字符的指针 TCHAR * pEndOfSrc = sSrc + nLenOfSrc -1; // 在比较过程中要用到的两个指针 TCHAR * pSrc = sSrc; TCHAR * pFind; // 总不能一直让它比较到 win.com 文件的地址去吧?嘻嘻! while ( pSrc <= pEndOfSrc ) { // 每次匹配都是从右向左,这是本算法的核心。 pFind = pEndOfFind; // 如果比较不成功,被查询串指针将向右串的字符数 int nMoveRightSrc; // 比较被查询串的当前字符是否和查询串的最右边字 // 符匹配,如果匹配则回溯比较,如果全匹配了,该 // 干什么,我就不用说了吧?:-) while ( pFind >= sFind ) { // TNND,白废功夫比了!看看需要向右移动几个 // 字符吧(如果说从右到左是本算法的核心,则 // 判断向右移几个字符则是本算法的技巧)。 if ( *pSrc != *pFind ) { // 被查询串的当前字符是否在查询串里? TCHAR * p = strrchr( sFind, *pSrc ); // 没在,直接移lstrlen(sFind)个字符 if ( NULL == p ) nMoveRightSrc = nLenOfFind; else // 哇塞!真的在,那就只需... nMoveRightSrc = pEndOfFind - p; break; } // 哈!又匹配成功了一个!接着向左回溯... pFind --; pSrc --; } // 如果在上面的while循环里每一次比较都匹配了 // 那就对了呗!告诉用户找到了 if ( pFind < sFind ) return ( pSrc + 1 ); // 没匹配成功,nMoveRightSrc上面已经算好了 // 直接用就可以了。 pSrc += nMoveRightSrc; } // 程序运行到这儿肯定是没指望了! return NULL; } 行了,函数写完了,我们可以试一下了! void CTNNDDlg::OnButton1() { TCHAR sSrc[] = "The rain in Spain"; TCHAR sFind[]= "pain"; TCHAR * pFound = BoyerMooreSearch( sSrc, sFind ); if ( pFound ) MessageBox(pFound); else MessageBox("没找到"); } //另外一个 void preBmBc(char *x, int m, int bmBc[]) { int i; for (i = 0; i < ASIZE; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[x[i]] = m - i - 1; } void suffixes(char *x, int m, int *suff) { int f, g, i; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && x[g] == x[g + m - 1 - f]) --g; suff[i] = f - g; } } } void preBmGs(char *x, int m, int bmGs[]) { int i, j, suff[XSIZE]; suffixes(x, m, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= -1; --i) if (i == -1 || suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; } void BM(char *x, int m, char *y, int n) { int i, j, bmGs[XSIZE], bmBc[ASIZE]; /* Preprocessing */ preBmGs(x, m, bmGs); preBmBc(x, m, bmBc); /* Searching */ j = 0; while (j <= n - m) { for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i); if (i < 0) { OUTPUT(j); j += bmGs[0]; } else j += MAX(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } }
❾ 字符串的模式匹配算法
#include<iostream>
using namespace std;
void Next(char T[],int next[])
{ next[0]=-1;
int j=0,k=-1;
while(T[j]!='\0')
if((k==-1)||(T[j]==T[k]))
{ j++;
k++;
next[j]=k;
}
else k=next[k];
}
int KMP(char S[],char T[])
{ int i=0,j=0;
int next[10];
Next(T,next);
while((S[i]!='\0')&&(T[j]!='\0'))
{ if(S[i]==T[j]) {i++;j++;}
else j=next[j];
if(j==-1)
{ i++;j++; }
}
if(T[j]=='\0') return(i-j+1);
else return 0;
}
int main()
{ char a[100],b[100];
cout<<"please enter primary string :";
cin.getline(a,100);
cout<<"please enter substring:";
cin.getline(b,100);
if(KMP(a,b)==0)
cout<<"not exist!\n";
else cout<<"location is:"<<KMP(a,b)<<endl;
return 0;
}
具体的你自己看吧。
❿ 字符串匹配算法,最快的是哪种
目前在我遇到的字符串匹配算法中,最快的应该是sunday算法了。。
(BF、KMP、BM、sunday)