字符串匹配
给定两个字符串A和B,判断B是否是A的字串,并返回B在A中第一次出现的位置。
如:
在上图中B是A的字串,B第一次在A中出现的位置下标是2,则返回2。
为了方便说,就把A串叫主串,把B串称模式串。
BF(暴力解法)
public class Main{
public static void main(String[] args) {
String A = "aayaaaaarb";
String B = "rbc";
System.out.print(solve(A,B));
}
public static int solve(String A, String B){
if(A.length() < B.length()) return -1; //如果模式串大于主串
int flag[] = new int[A.length()]; //用来记录模式串的首位在主串中的下标
int count = 0;
for(int j=0;j<A.length();j++){//循环找模式串首位在主串的下标
if(B.charAt(0) == A.charAt(j)) {
count++;
flag[count] = j;
}
}
for(int i=1;i<count+1;i++){
if(flag[i] + B.length() > A.length()) return -1;
String str = A.substring(flag[i],flag[i]+B.length());
if(B.equals(str)) return flag[i];
}
return -1;
}
}
RK(RabinKarp )
思路:
相对于逐个字符比较两个字符串,仅比较两个字符串的hashcode(哈希值)要容易得多。这里哈希值按照‘a’为1,‘b’为2…这样相加得到。当然哈希值相等并不代表匹配成功,比如abc与acb哈希值相等;
还需进一步利用equals()逐个字符比较两字符串。
public class Main{
public static void main(String[] args) {
String A = "aayaaaaarbcvv";
String B = "rbc";
System.out.print(solve(A,B));
}
public static int solve(String A, String B){
//先算出主串中与模式串等长的哈希值,如果相等
//再将串与模式串比较
int n = A.length(); //主串的长度
int m = B.length(); //模式串的长度
int patternCode = hash(B); //模式串的hash值
int strCode = hash(A.substring(0,m)); //求主串的局部哈希值
for(int i=0;i<n-m+1;i++){
if(patternCode == strCode && compare(i,i+m,A,B)) return i;
else if(i<n-m){
strCode = nexthash(A,strCode,i,i+m);
}
}
return -1;
}
private static int nexthash(String A, int strCode, int i, int j) {
strCode -= A.charAt(i)-'a';
strCode += A.charAt(j)-'a';
return strCode;
}
private static boolean compare(int i, int j, String b, String b2) {
return b.substring(i, j).equals(b2);
}
private static int hash(String str) {
int hasdcode=0;
for(int i = 0; i < str.length(); i++){
hasdcode += str.charAt(i)-'a';
}
return hasdcode;
}
}