Sunday算法:
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配。其核心思想是:在匹配过程中,模式串发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。
Sunday算法是从前往后匹配,在匹配失败时关注的是主串中参加匹配的最末位字符的下一位字符。
Sunday算法的JAVA实现:
public static int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
char[] a = haystack.toCharArray();
char[] b = needle.toCharArray();
int i = 0;
int j = 0;
//+ j是可能会出现最后一次移动a剩余长度与b长度不一致的情况
while (i <= a.length - b.length + j) {
if (a[i] != b[j]) {
//如果父串与子串当前字符不相等
if (i == a.length - b.length + j) {
//这里说明b已经是在和a中最后可能想等的字符比较过了,并且后面也没有可比较的了,所以返回
return -1;
}
//如果a的中间部分与b匹配,且结果不相等
//就从b最后面开始,找出子串最后一位的下一位对应a的字符在b中是否存在
int pos = contains(b, a[i - j + b.length]);
if (pos == -1) {
//不存在则直接跳到再下一位,子串从头开始
i = i - j + b.length + 1;
j = 0;
} else {
//存在则将这个字符与b最右边与它相同的字符对其,并再次从头开始比较
i = i + b.length - pos - j;
j = 0;
}
} else {
//如果a与b当前字符相等
if (j == b.length - 1) {
//如果比较到了b的最后一位,说明已经存在
return i - j;
} else {
//不是b最后一位,则进行下一个字符的对比
i++;
j++;
}
}
}
return -1;
}
/**
* 判断子串中是否存在末尾下一个位置对应的父串的字符
* 每次从后往前匹配,为了不遗漏可能的匹配,应该是跳到使得子串中最右一个字符与父串中的该字符对应,
* 这样跳过的距离最小,且是安全的。
*/
public static int contains(char[] sonArray, char ch) {
for (int i = sonArray.length - 1; i >= 0; i--) {
if (sonArray[i] == ch) {
return i;
}
}
return -1;
}