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     }

 

 

原文地址:https://www.cnblogs.com/dreamrun/p/4547779.html