sunday 算法--解决字符串匹配问题

一、Sunday 匹配机制
匹配机制非常容易理解:

目标字符串 haystack,长度为len

模式串 needle,长度为len_pattern

当前查询索引 idx (初始为 0)

待匹配字符串 search= haystack.substring(idx, idx + len_pattern),即从idx下标开始取长度len_pattern的字符串;

每次匹配都会从目标字符串中提取待匹配字符串模式串进行匹配:

若匹配,则返回当前 idx

不匹配,则查看待匹配字符串的后一位字符 c:

若c存在于模式串 needle中,则 idx = idx + 偏移表[c]

否则,idx = idx + len(needle)

Repeat Loop 直到 idx + len(needle) > len(haystack)

二、偏移表

偏移表的作用是存储每一个在 模式串 中出现的字符,在 模式串 中出现的最右位置到尾部的距离 +1+1

三、举例
String: checkthisout
Pattern: this

Step 1:

idx = 0
待匹配字符串为:chec
因为 chec != this
所以查看 chec 的下一个字符 k
k 不在 Pattern 里
所以查看 偏移表,idx = idx + 5
Step 2:


idx = 5
待匹配字符串为:this
因为 this == this
匹配,所以返回 5
四、算法分析
最坏情况:O(nm)
平均情况:O(n)

代码:

public static int sunday(String haystack, String needle) {
    // 几种特殊情况,快速剪枝
if (haystack.equals(needle) || needle.isEmpty()) return 0;
if (needle.length() > haystack.length()) return -1;
int idx = 0;
int len_pattern = needle.length();
int len_search = haystack.length();
int len = len_search;
while (len_search >= len_pattern && idx + len_pattern <= len) {
String sub = haystack.substring(idx, idx + len_pattern);
if (sub.equals(needle)) return idx;
else {
int pos = getPos(haystack.charAt(idx + len_pattern == len ? idx + len_pattern - 1 : idx + len_pattern), needle.toCharArray());
if (pos == -1) {
idx += len_pattern + 1;
} else {
// 找到字符
idx += len_pattern - pos;
}
len_search = len - idx;
}
}

return -1;
}

public static int getPos(char ch, char[] tmp) {
for (int i = tmp.length - 1; i >= 0; i--) {
if (tmp[i] == ch) return i;
}
return -1;
}
原文地址:https://www.cnblogs.com/majw/p/12134390.html