/********查找匹配字符串**********/
//最原始、复杂度最高的做法
//返回childstr在mumstr中第pos个字符之后的位置,如果不存在,则返回0
public int FindStr(String mumstr, String childstr, int pos)
{
//省去参数有效性判断
if((childstr.length() > mumstr.length()) || (pos >= mumstr.length()))
return 0;
char[] mumarr = mumstr.toCharArray();
char[] childarr = childstr.toCharArray();
int i = pos;
int j = 0;
while((i < mumarr.length) && ( j < childarr.length))
{
//如果匹配情况
if( mumarr[i] == childarr[j])
{
++i;
++j;
}
//如果不匹配,则从头开始匹配
else
{
i = i - j + 1;
j = 0;
}
}
//判断是否匹配成功,如果匹配成功,则跳出循环条件应该为 j = childarr.length情况
if( j >= childarr.length)
{
return i - j;
}
return 0;
}
/**************KMP算法*****************/
//KMP算法主要思想在于比较指针不回溯,通过计算next[j],将匹配指针回溯到next[j]位置与i位置的主字符串进行比较
//next[j]计算函数
/*初始化next[1] = 0;(注意实现时要注意算法中str的位置与算法中位置的区别)
且注意计算next[j]时,比较的是一直到j-1的字符串
next[j]计算共分为两种情况:记next[j] = k;
1.str[j] = str[k],则next[j + 1] = next[j] + 1 = k + 1;
2.若不等,则把比较想象成模式和主字符串都是childstr的模式匹配。则应该让str[j] 和str[next[k]]进行比较(这里记next[j] = k);
1) 相等,则next[j + 1] = next[k] + 1 = k' + 1;
2) 不相等,则继续令next[k] = k',将str[j]与str[k' + 1]作比较;
*/
private int[] getNext(String childstr)
{
//参数初始化
int length = childstr.length();
char[] childarr = childstr.toCharArray();
int next[] = new int[length];
next[0] = -1;//标志位字符串初始位
int i = 0;
int j = -1;
while ( i < length - 1)
{
if( i == 0 || j == -1 ||childarr[i] == childarr[j])//注意不能忘记j=-1的初始情况
{
next[++i] = ++j;
}
else
{
j = next[j];
}
}
return next;
}
/*******************KMP算法********************/
public int IndexKMP(String mumstr, String childstr, int pos)
{
if((childstr.length() > mumstr.length()) || (pos >= mumstr.length()))
return 0;
char[] mumarr = mumstr.toCharArray();
char[] childarr = childstr.toCharArray();
int i = pos;
int j = 0;
int[] next = getNext(childstr);
while ((i < mumarr.length)&&(j < childarr.length))
{
if(j == -1 || mumarr[i] == childarr[j])//注意还要加上j=-1的最初始化情况
{
++i;
++j;
}
else
{
//i不变,j变为next[j]
j = next[j];
}
}
if ( j >= childarr.length)
{
return i - j;
}
return 0;
}
public static void main(String[] args) {
StrMatch strMatch = new StrMatch();
String aString = "ababccddefgabcdefghij";
String bString = "ababccddefg";
System.out.println(strMatch.IndexKMP(aString, bString, 3));
}
/********改进的nextval算法********/
/*当遇到 a a a a b 情况
next[j] 0 1 2 3 4
nextval[j]0 0 0 0 1
即当比较到b时不等,回溯到next[4] = 3位置,比较a,仍不等则继续前移next[3] = 2;仍然是比较a,结果仍然是不等
故希望能够直接回溯至第一个a位置;
则改进算法中,next[j] = k; 若str[j] = str[k],则应和str[next[k]]进行比较,若str[j] = str[next[k]],则继续前移,
直至str[j]与其不相等;则next[j] = next[k],直至不相等的初始情况
*/
private int[] nextval(String childstr)
{
//参数初始化
int length = childstr.length();
char[] childarr = childstr.toCharArray();
int next[] = new int[length];
next[0] = -1;//标志位字符串初始位
int i = 0;
int j = -1;
while ( i < length - 1)
{
if( i == 0 || j == -1 ||childarr[i] == childarr[j])//注意不能忘记j=-1的初始情况
{
++i;
++j;
//再多一层对相等元素的判断
if(childarr[i] == childarr[j])//对应next[j] = next[k]情况
{
next[i] = next[j];
}
else
{
next[i] = j;
}
}
else
{
j = next[j];
}
}
return next;
}