实现字符串strstr()的功能,即从母串中查找子串第一次出现的位置(序号),没有出现则返回-1.
【思路】
刚开始学c时就学到过这个例子。
不同之处在于,这里参数是string,处理起来要比char*简单。
【my code】
int strStr(string haystack, string needle) { if(needle=="") return 0; if(haystack.size()<needle.size()) return -1; int i=0, j=0, k; for(i=0; i<=haystack.size()-needle.size(); i++) { k=i; j=0; while(j<needle.size()) { if(haystack[k]==needle[j]) { k++;j++; } else break; } if(j==needle.size()){ return i; } } return -1; }
【出现的问题】
1.输入("", "")和("abcd", ""),("a", "aaaa")的特殊情况都要考虑;
2.易错!——最外层for循环,i的范围应该在i<=haystack.size()-needle.size(),否则会发生越界,报错为:
time limit exceed(like this?)
一定要注意数组越界访问的问题!
【番外】
看到网上有用KMP实现的,复习一下。
1.求next的函数。
next的结果是保存了“下一步跳到哪个位置来比较”的数组,next的作用是子串“自匹配”,找到子串中重复的元素,这样母串与子串比较时,母串顺次遍历不回溯。
2.注意j=-1的情况,以及匹配不成功时,不是j=0,而是j=next[j],其余和上面思路一样。
3.发生了传说中的一个有意思的bug!
先把正确代码po出来——
【other code】
void getNext(string needle, int *next) { int j=-1; int i=0; next[0]=-1; while(i<needle.size()-1) { if(j==-1||needle[i]==needle[j]){ j++; i++; next[i]=j; } else j=next[j]; } } int strStr(string haystack, string needle) { int hlen = haystack.size(); int nlen = needle.size(); int *next=new int[nlen]; getNext(needle, next); int i=0, j=0; while(i < hlen&&j<nlen)//碰到传说中的情况!! { if(j==-1|| haystack[i]==needle[j]) { j++; i++; } else j=next[j]; } if(j==nlen) return i-j; else return -1; }
【高能预警】
当代码是这样的:
while(i < haystack.size()&&j<needle.size())
运行结果就会总是-1!!
因为.size()是无符号类型,j和它比较j会转换为无符号类型,但j在这里会等于-1!(next[0]=-1)
此时,j就是一个无符号的大数,永远不会==nlen。
所以在程序开始用两个int变量记住string的size是个明智的做法,而且还会减少每次输入xxx.size()的繁琐。