数据结构:串 kmp中next(val)数组(首位置为0即next[1]=0,其他公共长度+1)和不匹配j=next[j]

在匹配的过程中,直至匹配到不同的字符,主串和模式串之前的字符是相同的。到不匹配字符之前的字符的重复的部分是可以利用的

数组的计算方法

next[j]表示前 j-1 个串中首尾的公共长度+1,一号位(为零)除外

nextval[]在next的基础上,从左至右,第一个不变,从第二个字符开始,如果对应的next的值为c,在next[c-1]的字符如果与之相等,则将nextval的值置为nextval[c-1]

例如:

项目ABABAAABABAA
next011234223456
nextval010104210104

next[]中非零数i的表示模式串的第i个字符(arr[i-1]如果是数组的话)与不匹配位置开始比较

有公共前后缀的,前缀直接移动到后缀的位置。
一号位不匹配,与主串下一位进行比较
注意:比较时,从长公共前后缀的长度加1的位置开始与主串比较

模式串比较常用的存储方式是从下标1开始存储的(从零开始存储仍然可行)

递推,next数组的递推计算(长的不能手算的情况):

n e x t [ j + 1 ] = { n e x t [ j ] + 1 pj=pt n e x t [ t ] , 循 环 至 n e x t [ t ] = 0 或 者 满 足 ( 1 ) 为 止 pj!=pt next[j+1]= \begin{cases} next[j]+1& \text{pj=pt}\\ next[t],循环至next[t] = 0或者满足(1)为止& \text{pj!=pt} \end{cases} next[j+1]={next[j]+1next[t]next[t]=0(1)pj=ptpj!=pt

void getNext( Str substr, int next [] )
{
int  j=1,t=0;
   next[1]=0;
while(j < substr. length){
     if(t==0 || substr.ch[j] == substr.ch[t] ) {
     next[j+1] = t+1;//***\\\\
     ++t;
     ++j ;
     }
     else
      t = next[t] ;//头"指针"t的回溯***,♥下一次比较的位置♥
}
int: KMP (Str str, Str substr, int next[] )
{
 int i=1,j=1;//从str.ch[1]开始比较
while(i<r. length && j<=substr.length)//全部遍历(i,j的范围分别为珠串的范围和模式串的范围)
if(j==0||Istr.ch[i]==substr.ch[j])
  {++i ;
   ++j;//一个个字符按顺序比较
   }
   else 
  {
     j=next[j] ;//如果出现不匹配,直接移动
     //比如没有公共前后缀,j值就是1,比较 Istr.ch[i](当前位)==substr.ch[j](模式串的第一位)                                                      
   }
if (j>substr. length)
     return i-substr. length;
else
   return 0;
}

GTGTGCF
0111210
ATGTGAGCTGGTGTGCFGTGTG
GTGTGCF

其它相关代码

function getNext() {
    var  j=1,t=0;/*从前两位开始比较*/
    var next= []
    var target = [1,2,1,2,1,1,1,2,1,2,1,1];
    next[0]=66;
    next[1]=0;
    
    while(j < target.length){
     if(t==0 || target[j] == target[t] ) {
     next[j+1] = t+1;//***\\\\
     ++t;
     ++j ;console.log(next);
     }
     else
      {t = next[t] ;//头"指针"t的回溯***
       console.log(t);
       console.log(next);}
}
    console.log(next);
    return next;
}
getNext();
function getNext() {
    var  j=1,t=0;
    var next= []
    var target = [1,2,1,2,1,1,1,2,1,2,1,1];
    next[0]=514;
    next[1]=0;
    
    while(j < target.length){
     if(t==0 || target[j] == target[t] ) {
     next[j+1] = t+1;//***\\\\
     ++t;
     ++j ;
     }
     else
      t = next[t] ;//头"指针"t的回溯***
}
    console.log(next);
    return next;
}
void getNext( Str substr, int next [] )
{
int  j=1,t=0;
   next[1]=0;
   next[2]=1;
while(j < substr. length){
     if( substr.ch[j] == substr.ch[t] ) {
     next[j+1] = t+1;//***\\\\
     ++t;
     ++j ;
     }
     else {
     if(t==0){next[j+1] = 0;}
      else { t = next[t] ;}//头"指针"t的回溯***
      }
}

可以减少不必要的比较

void getNextval( Str substr, int nextval[],int next [] )
{
int  j=1,t=0;
   next[1]=0;
   Nextval[1]=0;
while(j < substr. length){
     if(t==0 || substr.ch[j] == substr.ch[t] ) {
     next[j+1] = t+1;
     //***
     if(substr.ch[j+1]!=substr.ch[substr.ch[j+1]]!)
           nextval[j+1]=next[j+1];
     else
        nextval[j+1] = nextval[next[j+1]];
      //***
     ++t;
     ++j ;
     }
     else
      t = nextval[t] ;//***
      t = next[t] ;
}
void getNextval( Str substr, int nextval[] )
{
int  j=1,t=0;
   Nextval[1]=0;
while(j < substr. length){
     if(t==0 || substr.ch[j] == substr.ch[t] ) {
   
     //***
     if(substr.ch[j+1]!=substr.ch[substr.ch[j+1]]!)
           nextval[j+1]=next[j+1];
     else
        nextval[j+1] = nextval[next[j+1]];
      //***
     ++t;
     ++j ;
     }
     else
      t = nextval[t] ;//***
   
}
class Untitled {
	public static void main(String[] args) {
		System.out.println("hello https://tool.lu/");
		String str="ATGTGAGCTGGTGTGCFGTGTG";
		String pattern="GTGTGCF";
	    int index=kmp(str ,pattern);
		System.out.println("首次出现位置:"+index);
	}

	// KMP算法主体逻辑。str是主串,pattern是模式串
	public static int kmp(String str, String pattern) {
		//预处理,生成next数组
			int[] next = getNexts (pattern);
		    intj=0;
		//主循环,遍历主串字符
		for (int i = 0; i < str.1ength(); i++) {
			while (j >0 && str.charAt(i) != pattern. charAt(j)) {
				//遇到坏字符时,查询next数组并改变模式串的起点
				j = next[j];
			}
			
		    if (str .charAt(i) == pattern. charAt(j)) {
				j++;
		    }
			
			if (j == pattern. length()) {
				//匹配成功,返回下标
            return i-pattern. length()+1;
			}

	  }
	}
	
	
	
	
	
	//生成Next数组
    private static int[] getNexts(String pattern) {
    int[] next = new int[pattern. length()];
    intj=0;
    for (int i=2; i<pattern.1ength(); i++) {
    while (j !=0&& pattern.charAt(j) != pattern.charAt(i-1)) {
    //从next[i+1]的求解回溯到next[j]
     j = next[j] ;
	}
    if (pattern. charAt(j) == pattern. charAt(i-1)) {
    j++;
	}
    next[i] = j;
	}
    return next;
	}
	
	
	
	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值