如:text=“abcdlijkfgd”,query=“abcdefg”,最大匹配为“abcd”,为4。编写一个函数,求字符串可匹配的最大长度。
如果是完全匹配,则用很多种方法,如BF,KMP,sunday等字符串匹配算法。KMP是比较常见的,其思想也值得学习,先用其抛下砖。
字符串完全匹配:
我们需要先求出字符串query的next数组,就是字符串前缀等于后缀的最大长度,这里不祥述。
移动规则:
第一趟:从起始位开始,在字符‘c’处不相同,此时i=3、j=3、next[j]为1,若next[j]不为-1,则令j = next[j],则j=1。
第二趟:j=1,i=3。字符'a'与‘c'不匹配,next[j]=0,j=0,i不变
第三趟:字符’a'与‘c'不匹配,此时next[j]=-1,如next[j]为-1,那么i加1,j等于0。相当于i=4,此时query的起始位与i=4对齐。
然后一直如此进行下去,直至找到匹配的子串。
上程序:
//KMP算法
void KMP(char text[], int lenText, char array[], int lenArray)
{
int *next = new int[lenArray];
next = getNext(array, lenArray);
int indexArray = 0;
for (int pos=0; pos<lenText; ++lenText)
{
while (text[pos] == array[indexArray])
{
++pos;
++indexArray;
}
if (next[indexArray] != -1)
{
indexArray = next[indexArray];
}
else
{
indexArray = 0;
}
}
}
int * getNext(char array[], int len)
{
int *next = new int[len];
next[0] = -1;
next[1] = 0;
for (int pos=2; pos<len; ++pos)
{
for (int k=1; k<pos; ++k)
{
int i=0;
int j=k;
int count = 0;
while (array[i] == array[j] && j<pos)
{
++count;
++i;
++j;
}
if (j == pos)
{
next[pos] = count;
break;
}
else
{
next[pos] = 0;
}
}
}
return next;
}
但是题目并不是完全匹配,只是要求匹配的最大长度。
我们看到,开始最大匹配长度为3,如红色部分;在最后我们得到了一个最大的匹配为4,显然4才是我们所求。
我们可以设置一个max变量。先从字符串“ababd”进行匹配,得到一个最大的匹配长度,赋给max。然后从字符串“babd”进行匹配,得到一个最大匹配长度,赋给max。直到将“d”与text进行匹配。这样我们就可以得到最大的字符串匹配长度。
改进:如果这其中可以匹配到最后一个字符串,那么就可以截止了。如“ababd”进行匹配时,如果匹配到字符‘d’,那么肯定已经得到最大的了;如果没有匹配到最后一个字符,最大匹配长度为4,那么进行第二趟匹配;从字符串“babd”进行匹配,如果匹配到最后一个字符,那么我们便得到了最大匹配长度4,便可结束。
编程时,我们每趟匹配,字符串长度变了,相应的next数组也要变化。