串(string)是由零个或多个字符组成的有限序列,又名叫字符串。
事实上,串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号。
计算机中的常用字符是使用标准的ASCII编码,由7位二进制数表示一个字符,总共可以表示128个字符。后来发现一些特殊符号的出现,128个不过,就扩展ASCII码由8位二进制数表示一个字符,总共可以表示256个字符。
后面针对其他国家语言文字,出现了Unicode编码,为了和ASCII兼容,前256个和ASCII码完全相同。
串的定位操作通常称作串的模式匹配
两种方法:
朴素模式匹配,从头到尾一个一个去匹配,效率低,好多重复的匹配操作
KMP模式匹配
#include<iostream>
using namespace std;
void makeNextArr(const char* tStr,int* next);
//KMP算法中,next数组中next[i]的值的含义就是:匹配串中0~i中的最大前后缀长度
void KMP(const char* sStr,const char* tStr);
void testNext(const char* tStr,int* next,int nextLen);
void test();
void makeNextArr(const char* tStr,int* next)
{
if(NULL==tStr||NULL==next)
return ;
int k = 0; //模式匹配最初k值设置为0
//k值表示如果匹配串的第0个字符和主串匹配失败,那么下一次还是用匹配串的第0个字符和主串的下一个字符开始匹配
next[0] = 0; //eg:S表示主串,T表示匹配串,S[i] != T[0],那么下次匹配 (S[i+1],T[0])
for(int idx = 1;idx<strlen(tStr);++idx) //循环计算其他next值
{
while(tStr[idx]!=tStr[k] &&
k>0) //计算下一个next的值,如果相等,累加k,不等就判断k值是否大于0,大于0就试着计算S[0]~S[k-1]中的最大前后缀
{
k = next[k-1]; //第0个字符,next[0] = 0;第k-1个字符,最大前后缀就是next[k-1]。
}
if(tStr[idx]==tStr[k])
++k;
next[idx] = k;
}
}
void KMP(const char* sStr,const char* tStr)
{
if(NULL==sStr||NULL==tStr)
return ;
int sStrLen = strlen(sStr);
int tStrLen = strlen(tStr);
int* next = new int[tStrLen]();
makeNextArr(tStr,next);
for(int idx=0,iidx=0;idx<sStrLen;++idx)
{
while(iidx>0&&
sStr[idx]!=tStr[iidx])
{
iidx = next[iidx-1]; //匹配串中第iidx个和主串第idx个不行等,减小回溯,比较匹配串中第next[iidx-1]个。
}
if(sStr[idx]==tStr[iidx])
{
++iidx; //iidx加到和匹配字符串长度相等的时候就表示找到一个子串
}
if(iidx==tStrLen)
{
cout<<"find sub str,pos is:"<<idx-(iidx-1)<<endl;
//有可能主串中有多个子串,利用next数组,减少回溯,查找下一个。
iidx = next[iidx-1];
}
}
}
|
void testNext(const char* tStr,int* next,int nextLen)
{
cout<<tStr<<endl;
makeNextArr(tStr,next);
for(int idx=0;idx<nextLen;++idx)
cout<<"next["<<idx<<"] = "<<next[idx]<<" ";
cout<<endl;
}
void test()
{
cout<<"---start test makeNextArr---"<<endl;
char* tStr = "abcdex";
int next[6];
testNext(tStr,next,6);
cout<<endl;
char* tStr2 = "abcabx";
int next2[6];
testNext(tStr2,next2,6);
cout<<endl;
char* tStr3 = "aaaaa";
int next3[6];
testNext(tStr3,next3,5);
cout<<endl;
char* tStr4 = "abcab";
int next4[5];
testNext(tStr4,next4,5);
cout<<endl;
char* tStr5 = "abaabb";
int next5[6];
testNext(tStr5,next5,6);
cout<<endl;
cout<<"---end test makeNextArr---"<<endl;
cout<<endl;
}
int main()
{
test();
char* sStr = "abcabcabc";
char* tStr = "abcab";
cout<<"主串:"<<sStr<<endl;
cout<<"匹配串:"<<tStr<<endl;
KMP(sStr,tStr);
cout<<endl;
char* sStr2 = "abcdefabcdef";
char* tStr2 = "abcab";
cout<<"主串:"<<sStr2<<endl;
cout<<"匹配串:"<<tStr2<<endl;
KMP(sStr2,tStr2);
system("pause");
}
|