zoukankan      html  css  js  c++  java
  • No.28 Implement strStr()

    No.28 Implement strStr()

    Implement strStr().

    Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

    分析:

      很经典的字符串匹配问题,若可以匹配,返回模式串在字符串中首次出现的下标;否则返回-1

      最容易想到的就是暴力破解了,但复杂度高,肯定不是首选。

      再就是经典的KMP算法,其实,之前看过好多次,但总是理解不了,后来就不了了之,这次看懂了,记录下。

    KMP:

      对于不懂KMP算法的人来说,先看看http://kb.cnblogs.com/page/176818/,对KMP有整体把握之后, 再看http://v.youku.com/v_show/id_XNzQzMjQ1OTYw.html视频可以很好的理解以下代码:

     

     1 class Solution
     2 {
     3 public:
     4     int strStr(string haystack, string needle)
     5     {//字符串搜索匹配:返回needle在haystack中首次出现的下标;若未出现,返回-1
     6         return KMP(haystack, needle);
     7     }
     8 
     9     //目的:计算部分匹配表,即next数组
    10     //输入:pattern模式串,next为next数组
    11     void getNext(string pattern, int next[])
    12     {
    13         int m = pattern.size();
    14         if(m==0)
    15             return;
    16 
    17         next[0] = -1;//表示的是0之前的串的前缀后缀相同的最大位数
    18         int index,j;
    19         for(int i=1; i<m; i++)
    20         {//next[i]其实表示的是,0~i-1这个字符串的最大相同前缀串和后缀串的长度
    21             j = i-1;
    22             index = next[j];
    23             while(index >=0 && pattern[index] != pattern[j])
    24                 index = next[index];
    25 
    26             if(index<0)
    27                 next[i] = 0;
    28             else//pattern[index] == pattern[j]
    29                 next[i] = index+1;
    30         }
    31     }
    32 
    33     //KMP算法
    34     //输入:text文本,pattern模式串;输出:成功则返回第一次匹配的位置;失败则返回-1
    35     int KMP(string text, string pattern)
    36     {
    37         int n = text.size();
    38         int m = pattern.size();
    39         if(n==0 && m==0)
    40             return 0;//根据题意,返回0!!
    41         if(m==0)
    42             return 0;//根据题意,返回0!!
    43         int *next = new int[m];
    44         getNext(pattern,next);
    45 
    46         int i=0, j = 0;
    47         while(i<n)
    48         {
    49             if(j==-1 || text[i] == pattern[j])
    50             //j==-1说明text[i]开头的字符串不可能和pattern匹配,所以text直接到下一个字符去
    51             {
    52                 i++;
    53                 j++;
    54             }
    55             else
    56                 j = next[j];
    57             if(j == m)//!!!匹配成功
    58                 return i-j;
    59         }
    60 
    61         delete[] next;
    62         return  -1;
    63     }        
    64 };
    65 int main()
    66 {
    67     Solution sol;
    68 
    69     cout << sol.strStr("abaabcabaddsacbads","abaabcaba")<<endl;
    70     cout << sol.strStr("BBCABCDABABCDABCDABDE","ABCDABD")<<endl;
    71     cout << sol.strStr("abcdefs","adg")<<endl;
    72     cout << sol.strStr("abcdefd","ebc")<<endl;
    73     cout << sol.strStr("","ebc")<<endl;
    74     return 0;
    75 }

     求解next数组的另一种方法:

     1     //目的:计算部分匹配表,即next数组
     2     //输入:pattern模式串,next为next数组
     3     void getNext(string pattern, int next[])
     4     {
     5         int m = pattern.size();
     6         if(m==0)
     7             return;
     8 
     9         next[0] = -1;//表示的是0之前的串的前缀后缀相同的最大位数
    10 
    11         int i=0,j=-1;//注意j=-1
    12         while(i < m-1)//范围控制到m-1
    13         {
    14             if(j==-1 || pattern[i] == pattern[j])
    15             {
    16                 i++;
    17                 j++;
    18                 next[i] = j;
    19             }
    20             else
    21                 j=next[j];
    22         }
    23             
    24     }

     暴力法:leetcode超时

     1 class Solution
     2 {
     3 public:
     4     int strStr(string haystack, string needle)
     5     {//字符串搜索匹配:返回needle在haystack中首次出现的下标;若未出现,返回-1
     6      //暴力法
     7         int n = haystack.size();//主串大小
     8         int m = needle.size();//模式串大小
     9 
    10         if(m == 0)
    11             return 0;
    12 
    13         int pn = 0;//指示主串下标
    14         int pm = 0;//指示模式串串下标
    15         int cur;//指示当前次匹配主串开始的位置,若匹配,则返回
    16         while(pn < n)
    17         {
    18             while(pn<n && haystack[pn] != needle[pm])
    19                 pn++;
    20             cur = pn;//找到与模式串首位置相同的位置,然后依次匹配
    21             pm++;
    22             pn++;
    23             while(pn<n && pm<m )
    24             {
    25                 if(haystack[pn] != needle[pm])
    26                     break;
    27                 pn++;
    28                 pm++;
    29             } 
    30 
    31             if(pm == m)
    32                 return cur;
    33             else
    34             {
    35                 pn = cur+1;
    36                 pm = 0;
    37             }
    38         }
    39         return -1;
    40     }

     

     

  • 相关阅读:
    04: Dom
    03: JavaScript基础
    02: css常用属性
    01: html常用标签
    03: Memcached
    01: Redis缓存系统
    01: RabbitMQ
    04: 事件驱动、五种I/O操作、I/O多路复用select和epoll
    03: 进程、线程、协程
    [Android] 任意时刻从子线程切换到主线程的实现
  • 原文地址:https://www.cnblogs.com/dreamrun/p/4547779.html
Copyright © 2011-2022 走看看