sunday算法的概念如下:
Sunday算法是Daniel M.Sunday于1990年提出的一种比BM算法搜索速度更快的算法。其核心思想是:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配,从而提高了匹配效率。
假设在发生不匹配时S[i]≠T[j],1≤i≤N,1≤j≤M。此时已经匹配的部分为u,并假设字符串u的长度为L。如图1。明显的,S[L+i+1]肯定要参加下一轮的匹配,并且T[M]至少要移动到这个位置(即模式串T至少向右移动一个字符的位置)。
图1 Sunday算法不匹配的情况
(1) S[L+i+1]在模式串T中没有出现。这个时候模式串T[0]移动到S[L+i+1]之后的字符的位置。如图2。
图 2 Sunday 算法移动的第 1 种情况
(2)S[L+i+1]在模式串中出现。这里S[L+i+1]从模式串T的右侧,即按T[M-1]、T[M-2]、…T[0]的次序查找。如果发现S[L+i+1]和T中的某个字符相同,则记下这个位置,记为k,1≤k≤M,且T[k]=S[L+i+1]。此时,应该把模式串T向右移动M-k个字符的位置,即移动到T[k]和S[L+i+1]对齐的位置。如图3。
依次类推,如果完全匹配了,则匹配成功 ; 否则,再进行下一轮的移动,直到 主串S 的待匹配长度小于模式串长度结束。
其算法实现如下,但只是最简单的实现,模式串中有重复字符会出错。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String total=scanner.nextLine();
String sub=scanner.nextLine();
int index=find(total,sub);
System.out.println(index);
scanner.close();
}
public static int find(String total, String sub) {
int pos=0;
int totalInc=0;
int tLength=total.length();
int sLength=sub.length();
int[] temp=new int[256];
for(int i=0;i<temp.length;i++){ //初始化
temp[i]=-1;
}
for(int i=0;i<tLength;i++){
for(int j=0;j<sLength;j++){
char c=total.charAt(i);
if(sub.charAt(j)==c&&temp[c]==-1){ //这里是求母串中的在模式串中从后往前
temp[c]=sLength-j; //数出现的位置,
break;
}
}
}
while(pos<tLength-sLength+1){ //开始匹配
int j=0;
int i=pos;
while(j<sLength){
if(total.charAt(i)==sub.charAt(j)){
i++;
j++;
}else{
break;
}
}
if(j==sLength) //匹配成功
return pos;
else{
int inc;
char c=total.charAt(pos+sLength);
if(temp[c]==-1)
inc=sLength+1;
else
inc=temp[c];
totalInc+=inc;
for(int k=0;k<totalInc;k++) //输出一次尝试的结果
System.out.print(" ");
System.out.println(sub);
pos=pos+inc;
}
}
return -1;
}
}