• KMP算法


    28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

    给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 

    示例 1:

    输入:haystack = "sadbutsad", needle = "sad"
    输出:0
    解释:"sad" 在下标 0 和 6 处匹配。
    第一个匹配项的下标是 0 ,所以返回 0 。
    

    示例 2:

    输入:haystack = "leetcode", needle = "leeto"
    输出:-1
    解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

    最常规直观

    直接src 字符串和 des 字符串,一个一个的比较,如果出现不一样,则src 开始位置前移一位,des 字符串从0 位置开始,再次比较,直到 src 字符串结束

    1. public int strStr(String haystack, String needle) {
    2. if(haystack==null || needle==null || haystack.isEmpty() || needle.isEmpty())
    3. return -1;
    4. int len1=haystack.length(),len2=needle.length();
    5. for(int i=0;i
    6. int j=0;
    7. for(;j
    8. if(haystack.charAt(i+j) != needle.charAt(j)){
    9. break;
    10. }
    11. }
    12. if(j==len2){
    13. return i;
    14. }
    15. }
    16. return -1;
    17. }

    KMP 算法

    src      >abcdabefgh 

    dst      >adcdadf   

    当比较到 adcdab 后,就出现了不一样,这个时候从头开始又比较;KMP 算法优化这里;

    1、获取 dst 字符串的子串相同前缀后缀长度

    子串a同前缀后缀    ->0         f(0)=0

    子串ad同前缀后缀  ->0        

    子串adc同前缀后缀  ->0

    子串adcd同前缀后缀  ->0

    子串adcda同前缀后缀  -> a  ->1

    子串adcdad同前缀后缀->ad ->2

    .......

    f(n)=    f(n-1)>0,则比较最后一个字符串和f(n-1)对于字符串的f(n-1)+1 位置是否相等

               f(n-1)=0,则比较最后一个字符串跟首字符串是否相等

    KMP 算法,暴力匹配获取子串同前缀后缀长度

    字符串 aabaaab

    KMP[0]=0
    KMP[1]=1
    KMP[2]=0
    KMP[3]=1
    KMP[4]=2
    KMP[5]=2
    KMP[6]=3
     

    1. public static void KMP_string(String s,int[] KMP){
    2. //i 表示字符串字串长度,0~len-1
    3. for(int i=0;i
    4. //j 表示从j=1 开始跟字串从k=0开始比较,直到子串结束
    5. int j=1,k=0;
    6. for(;j<=i;j++){
    7. if(s.charAt(k) == s.charAt(j)){//对应位置相等,j、k 下个位置
    8. k++;
    9. continue;
    10. }else{
    11. //对应位置不相等,字串回到0 位置,跟字串比较的也回退k 个位置
    12. j-=k;
    13. k=0;
    14. }
    15. }
    16. KMP[i]=k;
    17. }
    18. }

    使用递归计算KMP,递归使用上一次最长前后缀,这样每次只需要比较最后一个位置字符一次

    伤神呀,不过按照自己的理解了,写出来还是比较快

    1. public static void KMP_string(String s,int[] KMP){
    2. //i 表示字符串字串长度,0~len-1
    3. for(int i=0;i
    4. //j 表示从j=1 开始跟字串从k=0开始比较,直到子串结束
    5. int j=1,k=0;
    6. if(i==0){
    7. KMP[i]=0;
    8. continue;
    9. }
    10. if(KMP[i-1]>0){
    11. if(s.charAt(i)==s.charAt(KMP[i-1]))
    12. KMP[i]=KMP[i-1]+1;
    13. // else if (s.charAt(i)==s.charAt(0))
    14. // KMP[i]=1;
    15. // else
    16. // KMP[i]=0;
    17. else{
    18. //这个时候将Prefix==>s[0~i-1] 当成子串,目标串(前缀),suffix==>s[len(s[0~i-1])-KMP[i-1],i] 为源串(后缀),
    19. // 这个时候要从源串中找到目标串在源串的位置
    20. //aabaaab
    21. //i=0时候,s[0]="a"
    22. //i=1,字符串“aa” 这个时候将Prefix=>s[0~0]="a" , suffix=>s[1~1]="a"
    23. //i=2,字符串“aab” 这个时候将Prefix=>s[0~0]="aa" , suffix=>s[1~1]="ab",从suffix中找跟Prefix最长匹配
    24. //i=3,字符串“aaba” Prefix=>s[0~0]="aab" suffix=>s[1~1]="aba"
    25. //当i=n时,从i=n-1 时匹配的位置开始匹配前缀和后缀,最后一个字符不匹配,那这个时候Prefix 后退到0 位置,
    26. // suffix 后退到i=n-1时suffix对应的最长相同前后缀位置,即KMP[n-1]
    27. k=0;//refix 后退到0 位置
    28. j=i-KMP[i-1];//suffix 后退到上次最长相同前后缀位置
    29. /*
    30. while(k<=i && j<=i){
    31. if(s.charAt(k)==s.charAt(j)){
    32. k++;
    33. j++;
    34. }else{
    35. //再次取
    36. }
    37. }*/
    38. //由于前后缀一样KMP[i-1]个长度一样
    39. k+=KMP[i-1];
    40. j+=KMP[i-1];
    41. int loop=i-1;
    42. k=KMP[loop];
    43. j=i;
    44. while(loop>=0){
    45. if(s.charAt(k)==s.charAt(j)){
    46. KMP[i]=k+1;
    47. break;
    48. }else{
    49. loop--;
    50. if(loop<0){
    51. KMP[i]=0;
    52. }else {
    53. k = KMP[loop];
    54. }
    55. }
    56. }
    57. }
    58. }else{
    59. if (s.charAt(i)==s.charAt(0)){
    60. KMP[i]=1;
    61. }else{
    62. KMP[i]=0;
    63. }
    64. }
    65. }
    66. }

    116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)

    1. /*
    2. // Definition for a Node.
    3. class Node {
    4. public int val;
    5. public Node left;
    6. public Node right;
    7. public Node next;
    8. public Node() {}
    9. public Node(int _val) {
    10. val = _val;
    11. }
    12. public Node(int _val, Node _left, Node _right, Node _next) {
    13. val = _val;
    14. left = _left;
    15. right = _right;
    16. next = _next;
    17. }
    18. };
    19. */
    20. class Solution {
    21. public Node connect(Node root) {
    22. setNext(root);
    23. setLayerNext(root);
    24. showNode(root);
    25. return root;
    26. }
    27. public void setNext(Node root){
    28. if(root == null) return;
    29. if(root.left != null){
    30. root.left.next = root.right;
    31. }
    32. setNext(root.left);
    33. setNext(root.right);
    34. }
    35. public void setLayerNext(Node root){
    36. if(root == null) return;
    37. if(root.next != null){
    38. if(root.right != null && root.next != null){
    39. root.right.next = root.next.left;
    40. }
    41. }
    42. setLayerNext(root.left);
    43. setLayerNext(root.right);
    44. }
    45. public void showNode(Node root){
    46. Node myNode = root;
    47. if(root == null) return;
    48. if(root.next == null){
    49. System.out.print(root.val);
    50. System.out.print("#");
    51. }else{
    52. while(myNode.next != null){
    53. System.out.print(myNode.next.val);
    54. myNode = myNode.next;
    55. if(myNode == null){
    56. System.out.print("#");
    57. }
    58. }
    59. }
    60. if(root.left != null){
    61. showNode(root.left);
    62. }
    63. }
    64. }

  • 相关阅读:
    不要小看一个Redis~ 从头到尾全是精华,阿里Redis速成笔记太香了
    安卓毕业设计app项目源码移动端的医生寻访平台
    绿色荧光素标记纤维素;FITC-Cellulose/Cellulose-Fluorescein
    HTML5七夕情人节表白网页制作【唯美3D相册】HTML+CSS+JavaScript
    图解 MySQL 索引,清晰易懂,写得太好了!
    深入理解HTTPS协议原理
    [羊城杯 2022]LRSA
    如何使用css实现一个加载动画
    java常见集合框架的区别
    Java-校验规则Integer使用 @NotEmpty注解报错
  • 原文地址:https://blog.csdn.net/lei7143/article/details/133188929