zoukankan      html  css  js  c++  java
  • kmp 学习【字符串-kmp学习】

    最近学算法,了解了一些好玩的东西。
    KMP算法(Knuth-Morris-Pratt)的K的指的是计算机大佬 高德纳
    大神就是大神,人生经历牛逼。
    昨天在看舞蹈链的知识(也是高德纳大神发明的୧(๑•̀◡•́๑)૭)

    分析

    为了能够理解AC自动机,我又看起了KMP,这个KMP最难理解的还是next数组
    就是那一句k=next[k],太难理解了。
    写的话还是能把KMP写出来的。
    首先写暴力算法,在暴力算法的基础上写出kmp算法,至于get_next()结构和kmp算法很想,再此基础上略微改变就行。

    kmp算法通过取消了主串的回溯,来加快算法。
    因为有一些比较是多余的,可以通过模式串的结构来简化这个过程。
    next数组的一个核心概念就是前缀和后缀。
    它求的是一个字符串的相同的最大前缀和最大后缀的长度。

    至于以前一直困扰我的next数组赋值的问题,最近想明白了,其实他们是一致的,多1少1无非是为了程序好写。

    My Code

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1e6+5;
    
    int NEXT[maxn];
    int bf(char* source,char *pattern )
    {
    	int n=strlen(source);
    	int m=strlen(pattern);
    	int i=0;
    	int j=0;
    	while(i<n&&j<m)
    	{
    		if(source[i]==pattern[j])
    		{
    			i++;
    			j++;
    		}
    		else
    		{
    			i=i-j+1;
    			j=0;			
    		}
    	}
    	if(j==m)
    		return i-j;
    	else
    		return -1;
    }
    
    int kmp(char* source,char *pattern )
    {
    	int n=strlen(source);
    	int m=strlen(pattern);
    	int i=0;
    	int j=0;
    	while(i<n&&j<m)
    	{
    		if(j==-1||source[i]==pattern[j])
    		{
    			i++;
    			j++;
    		}
    		else
    		{
    			j=NEXT[j];
    		}
    	}
    	if(j==m)
    		return i-j;
    	else
    		return -1;
    }
    
    
    void GetNext(char* pattern)
    {
    	int pLen = strlen(p);
    	NEXT[0] = -1;
    	int k = -1;
    	int j = 0;
    	while (j < pLen - 1)
    	{
    		//p[k]表示前缀,p[j]表示后缀
    		if (k == -1 || p[j] == p[k]) 
    		{
    			++k;
    			++j;
    			NEXT[j] = k;
    		}
    		else 
    		{
    			k = NEXT[k];
    		}
    	}
    }
    
    
    
    int main()
    {
    	/*
    	// 指针初始化 字符串常量, 内存分配在全局的const内存区,需要加上const
    	char* source="BBC ABCDAB ABCDABCDABDE";	
    	char* pattern="ABCDABD";
    	
    	// 正确的初始化操作
    	char* source="BBC ABCDAB ABCDABCDABDE";
    	char* pattern="ABCDABD";
    	
    	char source[]="BBC ABCDAB ABCDABCDABDE";
    	char pattern[]="ABCDABD";
    	*/
    	char source[]="BBC ABCDAB ABCDABCDABDE";
    	char pattern[]="ABCDABD";	
    	printf("%s
    ",source);
    	printf("%s
    ",pattern);
    	cout<<bf(source,pattern)<<endl;
    	GetNext(pattern);
    	cout<<kmp(source,pattern)<<endl;;
        return 0;
    }
    
  • 相关阅读:
    w3cscholl的在线代码编辑工具2
    w3cscholl的在线代码编辑工具
    关于 stl的内存分配的深浅拷贝
    色彩模式与色彩空间
    mediacoder固定质量CRF
    集合加泛型的类型转换
    JQuery事件绑定bind、live、on、trigger
    JS构造函数中有return
    SSA与ASS字幕
    同步、异步、阻塞、非阻塞区别与联系
  • 原文地址:https://www.cnblogs.com/shengwang/p/9779449.html
Copyright © 2011-2022 走看看