一、前言
从模式串中查找目标串的首字母下标,不存在则返回-1
二、算法思路
方法一:暴力求解
宽度为目标串长度的窗口从左向右移动,判断窗口内的每个字符是否与目标串对应的字符相等,若不相等则窗口右移一格,重复之前的操作。
方法二:Robin Karp算法
将字符串转换成R进制的数(其中R为素数,素数哈希冲突的可能性小),利用哈希函数的特征,如果哈希值不同则字符串一定不相等,如果哈希值相同,则字符串可能相等。hash函数采用除留取余的方式。
三、算法Java实现
方法一:暴力求解
public class Solution {
/**
* @param source: A source string
* @param target: A target string
* @return: An integer as index
*/
public int strStr(String source, String target) {
//外层循环控制窗口右移
for (int i = 0; i < source.length() - target.length() + 1; ++i) {
boolean flag = true;
//内层循环比较窗口内的字符
for (int j = 0; j < target.length(); ++j) {
if(source.charAt(i + j) != target.charAt(j)){
flag = false;
break;
}
}
if(flag){
return i;
}
}
return -1;
}
}
方法二:Robin Karp算法
public class Solution {
/**
* @param source: A source string
* @param target: A target string
* @return: An integer as index
*/
public int strStr(String source, String target) {
if(source == null || target == null){
return -1;
}
if(source.length() < target.length()){
return -1;
}
if(target.length() == 0){
return 0;
}
int R = 31, Q=10000000;
int power=1;
//计算R的target.length()次方 取余防止溢出
for (int i = 0; i < target.length(); i++) {
power = (power * R) % Q;
}
//R进制计算公式:a0 + a1*R + a2*R^2 + ... + an*R^n
//将目标串转换为R进制数的hash值
int targetHash = 0;
for (int i = 0; i < target.length(); i++) {
targetHash = (targetHash * R + target.charAt(i)) % Q;
}
//计算各子串的hash值
int sourceHash = 0;
for (int i = 0; i < source.length(); i++) {
sourceHash = (sourceHash * R + source.charAt(i)) % Q;
if(i < target.length() - 1){
continue;
}
if(i > target.length() - 1){
sourceHash = sourceHash - (source.charAt(i - target.length()) * power) % Q;
}
if(sourceHash < 0){
sourceHash += Q;
}
if(targetHash == sourceHash && target.equals(source.substring(i - target.length() + 1, i + 1))){
return i - target.length() + 1;
}
}
return -1;
}
}