当前位置: 首页 > news >正文

实现 strStr()采用kmp算法

实现 strStr() (implement-strstr)

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

最简单的

	public int strStr(String haystack, String needle) {
		if(haystack.length()<needle.length())return -1;
		return haystack.indexOf(needle);
	}

暴力搜索

java语言

	//a needle in haystack
	public int strStr_2(String haystack, String needle) {
		int pLen = needle.length();
		int sLen = haystack.length();
		
		int i = 0;
		int j = 0;
		while(i<sLen&&j<pLen) {
			if(haystack.charAt(i)==needle.charAt(j)) {
				//①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++    
				i++;
				j++;
			}else {
				//②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0    
				i = i-j+1;
				j=0;
			}
		}
		//匹配成功,返回模式串p在文本串s中的位置,否则返回-1
		if (j == pLen)
			return i - j;
		else
			return -1;
	}

c语言

int ViolentMatch(char* s, char* p)
{
	int sLen = strlen(s);
	int pLen = strlen(p);
 
	int i = 0;
	int j = 0;
	while (i < sLen && j < pLen)
	{
		if (s[i] == p[j])
		{
			//①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++    
			i++;
			j++;
		}
		else
		{
			//②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0    
			i = i - j + 1;
			j = 0;
		}
	}
	//匹配成功,返回模式串p在文本串s中的位置,否则返回-1
	if (j == pLen)
		return i - j;
	else
		return -1;
}

KMP算法

next数组生成原理

next数组生成

#include<stdio.h>

//gcc kmp.c -o kmp
// $ ./kmp

void prefix_table(char pattern[],int prefix[],int n){
  prefix[0]=0;
  int len = 0;
  int i=1;
  while(i<n){
    if(pattern[i]==pattern[len]){
      len++;
      prefix[i]=len;
      i++;
    }else{
      if(len>0){
        len = prefix[len-1];
      }else{
        prefix[i]=len;
        i++;
      }
    }
  }
}

int main(){
  char pattern[] = "ABABCABAA";
  int prefix[9];
  int n=9;

  prefix_table(pattern,prefix,n);

  int i;
  for(i=0;i<n;i++){
    printf("%d\n",prefix[i]);
  }
  return 0;
}

输出

0
0
1
2
0
1
2
3
1

next数组后移一位,前面加上-1

next数组后移一位,前面加上-1,是为了方便匹配。

#include<stdio.h>

//gcc kmp.c -o kmp
// $ ./kmp

void prefix_table(char pattern[],int prefix[],int n){
  prefix[0]=0;
  int len = 0;
  int i=1;
  while(i<n){
    if(pattern[i]==pattern[len]){
      len++;
      prefix[i]=len;
      i++;
    }else{
      if(len>0){
        len = prefix[len-1];
      }else{
        prefix[i]=len;
        i++;
      }
    }
  }
}

//next数组向前移动一位,方便kmp算法
void move_prefix_table(int prefix[],int n){
  int i;
  for(i=n-1;i>0;i--){
    prefix[i] = prefix[i-1];
  }
  prefix[0] = -1;
}

int main(){
  char pattern[] = "ABABCABAA";
  int prefix[9];
  int n=9;

  prefix_table(pattern,prefix,n);
  move_prefix_table(prefix,n);

  int i;
  for(i=0;i<n;i++){
    printf("%d\n",prefix[i]);
  }
  return 0;
}

执行gcc kmp.c -o kmp./kmp
输出

-1
0
0
1
2
0
1
2
3

kmp完整代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//gcc kmp.c -o kmp
// $ ./kmp


void prefix_table(char pattern[],int prefix[],int n){
  prefix[0]=0;
  int len = 0;
  int i=1;
  while(i<n){
    if(pattern[i]==pattern[len]){
      len++;
      prefix[i]=len;
      i++;
    }else{
      if(len>0){
        len = prefix[len-1];
      }else{
        prefix[i]=len;
        i++;
      }
    }
  }
}

//next数组向前移动一位,方便kmp算法
void move_prefix_table(int prefix[],int n){
  int i;
  for(i=n-1;i>0;i--){
    prefix[i] = prefix[i-1];
  }
  prefix[0] = -1;
}

void kmp_search(char text[],char pattern[]){
    int n = strlen(pattern);
    int m = strlen(text);
    int* prefix = malloc(sizeof(int) * n);
    prefix_table(pattern,prefix,n);
    move_prefix_table(prefix,n);

    //text[i]   , len(text)    =m
    //pattern[j], len(pattern) =n

    int i = 0;
    int j = 0;
    while(i<m){
      if(j==n-1 && text[i] == pattern[j]){
        printf("Found pattern at %d\n",i-j);
        j = prefix[j];
      }
      if(text[i]==pattern[j]){
        i++;j++;
      }
      else{
        j = prefix[j];
        if(j==-1){
          i++;j++;
        }
      }
    }
 }

int main(){
  char pattern[] = "ABABCABAA";
  char text[]    = "ABABABCABAABABABAB";
  kmp_search(text,pattern);
  /*
  int prefix[9];
  int n=9;

  prefix_table(pattern,prefix,n);
  move_prefix_table(prefix,n);

  int i;
  for(i=0;i<n;i++){
    printf("%d\n",prefix[i]);
  }
  */
  return 0;
}

输出Found pattern at 2

相关文章:

  • translate-shell的使用方法
  • ksnapshot使用
  • 报数count-and-say
  • 递归需要遵守的重要规则
  • 组合总和(combination-sum)
  • 组合总和combination-sum
  • 如何查看隐藏的密码(限chrome浏览器)
  • 最大子序和(maximum-subarray)——动态规划和贪心双解法
  • Deepin系统安装SSH服务
  • Deepin Gif转mp4
  • 零钱兑换(coin-change) 动态规划问题
  • 批量识别图版中的文字信息之百度AI文字识别
  • 操作系统 术语表
  • GoldenDict 调用百度翻译(多段文本)
  • Hexo常用命令
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • crontab执行失败的多种原因
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • js面向对象
  • leetcode386. Lexicographical Numbers
  • mysql 数据库四种事务隔离级别
  • nginx 负载服务器优化
  • Redis中的lru算法实现
  • windows下mongoDB的环境配置
  • 高性能JavaScript阅读简记(三)
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 简单易用的leetcode开发测试工具(npm)
  • 我有几个粽子,和一个故事
  • 小试R空间处理新库sf
  • 用mpvue开发微信小程序
  • 正则表达式小结
  • Android开发者必备:推荐一款助力开发的开源APP
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #Linux(Source Insight安装及工程建立)
  • #QT(TCP网络编程-服务端)
  • #微信小程序(布局、渲染层基础知识)
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (1)(1.13) SiK无线电高级配置(五)
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (175)FPGA门控时钟技术
  • (C++17) optional的使用
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (十六)一篇文章学会Java的常用API
  • (转)大道至简,职场上做人做事做管理
  • (转)详解PHP处理密码的几种方式
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • *Django中的Ajax 纯js的书写样式1
  • .NET 的程序集加载上下文
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)