实现strstr(****)
版本一
求next數組(個人最習慣的寫法)
構造next數組其實就是計算模式串s,前綴表的過程。」 主要有如下三步:
1、初始化
2、處理前后綴不相同的情況
3、處理前后綴相同的情況
代碼實現
class Solution { public:void getNext(int* next,const string &s){int j=0;next[0]=j;for(int i=1;i<s.size();i++){while(j>0 && s[i]!=s[j]){j=next[j-1];}if(s[i]==s[j]){j++;}next[i]=j;} }int strStr(string haystack, string needle) {if (needle.size() == 0) {return 0;}int next[needle.size()];getNext(next, needle);int j = 0; // // 因為next數組里記錄的起始位置為-1for (int i = 0; i < haystack.size(); i++) { // 注意i就從0開始while(j > 0 && haystack[i] != needle[j]) { // 不匹配j = next[j-1]; // j 尋找之前匹配的位置}if (haystack[i] == needle[j ]) { // 匹配,j和i同時向后移動 j++; }if (j == (needle.size() ) ) { // 文本串s里出現了模式串treturn (i - needle.size() + 1); }}return -1;} };版本二
求next數組(-1操作)
如果我們這樣寫
void getNext(int* next, const string& s){int j = 0;next[0] = j;for(int i = 1; i < s.size(); i++) { // 注意i從1開始while (j >= 0 && s[i] != s[j]) { // 前后綴不相同了j = next[j]; // 向前回溯}if (s[i] == s[j]) { // 找到相同的前后綴j++;}next[i] = j; // 將j(前綴的長度)賦給next[i]} }那么構造前綴表的時候會陷入死循環,而不是文本串 與 模式串匹配的時候陷入死循環。
此時i與j并不相同,那么j需要回退,此時j = 1,而next[1]=1,j = next[j]陷入死循環。
初始化
定義兩個指針i和j,j指向前綴末尾位置(嚴格來說是末尾位置減一的位置),i指向后綴末尾位置。
然后還要對next數組進行初始化賦值,如下:
j 為什么要初始化為 -1呢,是因為之前說過 前綴表要統一進行減一的操作
next[i] 表示 i(包括i)之前的子串最長相等的前后綴長度(其實就是j)所以初始化next[0] = j 。
處理前后綴不相同的情況
因為j初始化為-1,所以遍歷模式串s的循環下表i 要從 1開始,進行s[i] 與 s[j+1]的比較。
for(int i = 1; i < s.size(); i++) {如果 s[i] 與 s[j+1]不相同,也就是遇到 前后綴末尾不相同的情況,就要向前回溯。
怎么回溯呢?
next[j]就是記錄著j(包括j)之前的子串的相同前后綴的長度。
那么 s[i] 與 s[j+1] 不相同,就要找 j+1前一個元素在next數組里的值(就是next[j])。
while (j >= 0 && s[i] != s[j + 1]) { // 前后綴不相同了j = next[j]; // 向前回溯 }處理前后綴相同的情況
如果s[i] 與 s[j + 1] 相同,那么就同時向后移動i 和j 說明找到了相同的前后綴,同時還要將j(前綴的長度)賦給next[i], 因為next[i]要記錄相同前后綴的長度。
if (s[i] == s[j + 1]) { // 找到相同的前后綴j++; } next[i] = j;Next數組代碼實現
void getNext(int* next,string &s){int j=-1;next[0]=j;for(int i=1;i<s.size();i++){// 注意i從1開始//j>=0是因為j初始值為-1,當ab,j+1指向a的時候,不加j>=0這個條件,j會回退到當前位置的前一個位置所對應的next數組的值,即j=next[j+1-1](j=next[-1])的位置造成內存越界。while(j>=0 && s[i]!=s[j+1]){// 前后綴不相同了j=next[j];// 向前回溯}if(s[i]==s[j+1]){// 找到相同的前后綴j++;}next[i]=j;//將j(前綴的長度)賦給next[i]} }整體代碼實現
class Solution { public://根據模式串求next數組void getNext(int* next,string &s){int j=-1;next[0]=j;for(int i=1;i<s.size();i++){//j>=0是因為j初始值為-1,當ab,j+1指向a的時候,不加j>=0這個條件,j會回退到當前位置的前一個位置所對應的next數組的值,即j=next[j+1-1](j=next[-1])的位置造成內存越界。while(j>=0 && s[i]!=s[j+1]){j=next[j];}if(s[i]==s[j+1]){j++;}next[i]=j;} }int strStr(string haystack, string needle) {if (needle.size() == 0) {return 0;}int next[needle.size()];getNext(next, needle);int j = 0; // // 因為next數組里記錄的起始位置為-1for (int i = 0; i < haystack.size(); i++) { // 注意i就從0開始while(j > 0 && haystack[i] != needle[j]) { // 不匹配j = next[j-1]+1; // j 尋找之前匹配的位置}if (haystack[i] == needle[j]) { // 匹配,j和i同時向后移動 j++; }if (j == (needle.size() ) ) { // 文本串s里出現了模式串treturn (i - needle.size() + 1); }}return -1;} };個人建議使用版本一 易理解
總結
以上是生活随笔為你收集整理的实现strstr(****)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 翻转字符串里面的单词(*****)
- 下一篇: 重复的子字符串