对于两个字符串A,B。请设计一个高效算法,找到B在A中第一次出现的起始位置。若B未在A中出现,则返回-1。
给定两个字符串A和B,及它们的长度lena和lenb,请返回题目所求的答案。
测试样例:
"acbc",4,"bc",2
返回:2
class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { // 不建议暴力求解,掌握KMP多好 // 考察基本的KMP字符匹配算法,时间复杂度相当好O(n) return kmp(A, B); } int kmp(const string& t, const string& str) { int n = t.length(); int m = str.length(); if (n < m) return -1; vector<int> pre(m, 0); int k = 0; for (int i = 1; i < m; ++i) { while (k > 0 && str[k] != str[i]) k = pre[k]; if (str[i] == str[k]) k += 1; pre[i] = k; } int q = 0; for (int i = 0; i < n; ++i) { while (q > 0 && t[i] != str[q]) q = pre[q]; if (t[i] == str[q]) q += 1; if (q == m) return i - m + 1; } return -1; } };
/* 第一种方法 */ import java.util.*; public class StringPattern { public int findAppearance(String A, int lena, String B, int lenb) { // write code here int result=A.indexOf(B); return result; } } /*第二种方法*/ import java.util.*; public class StringPattern { public int findAppearance(String A, int lena, String B, int lenb) { //判断长度 // char[] ch1=A.toCharArray(); //char[] ch2=B.toCharArray(); if(lena<lenb) return -1; if(lena==lenb) { if(A.equals(B)) return 0; else return -1 ; } //lena>lenb //截取字符串。 //遍历一遍,记录B字符串首字符出现的位置 int i=0; while(i<=lena-lenb) { // if(ch1[i]==ch2[0]) if(A.charAt(i)==B.charAt(0)) { String temp=A.substring(i,i+lenb); if(temp.equals(B)) return i; else { i++; continue; } } i++; } return -1; } }
//话说一年前我看KMP算法被虐的生活不能自理 //如今秒懂 //不过去年学的python,今年重新投入C++的怀抱 //看来python只是适合上手,学算法啥的还是C++清晰明了 class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { // write code here return kmp(A.c_str(), lena, B.c_str(), lenb); } private: //next static void compute_prefix(const char *pattern, int next[]) { int i; //j表示既是自身真后缀又是最长前缀的字符串长度 int j = -1; const int m = strlen(pattern); next[0] = j; for (i = 1; i < m; i++) { //失配的操作 //递归调用next,直到整个pattern再无最长前缀或者找到一个之前的满足条件的最长前缀 while (j > -1 && pattern[j + 1] != pattern[i]) j = next[j]; if (pattern[i] == pattern[j + 1]) j++; next[i] = j; } } //kmp static int kmp(const char *text, int m, const char *pattern, int n) { int i; int j = -1; //const int m = strlen(text); //const int n = strlen(pattern); int *next = new int[n]; compute_prefix(pattern, next); for (i = 0; i < m; i++) { while (j > -1 && pattern[j + 1] != text[i]) j = next[j]; if (text[i] == pattern[j + 1]) j++; if (j == n - 1) { //记得delete delete []next; return i - j; } } delete []next; return -1; } };
class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { // write code here if(lenb > lena) return -1; if(lenb == 0) return 0; int j = 0; for(int i = 0; i < lena;i++) { if(A[i] == B[j]) j++; else j = 0; if( j == lenb ) return i - j + 1; } return -1; } };
//这个错哪了? if(lena<lenb) return -1; if(lena==lenb) { if(strcmp(A.c_str(),B.c_str())==0) return 0; else return -1; } int i = 0; while(i<=(lena-lenb)) { if(A[i]==B[0]) { string temp = A.substr(i,i+lenb); if(strcmp(temp.c_str(),B.c_str())==0) { return i; } else { i++; continue; } } i++; } return -1;
import java.util.*; public class StringPattern { public int findAppearance(String A, int lena, String B, int lenb) { char[] charA = A.toCharArray(); char[] charB = B.toCharArray(); int i = 0; int j = 0; while (i < lena && j < lenb) { if(charA[i] == charB[j]){ i++; j++; } else { i = i - (j -1); j = 0; } } if(j == lenb) { return i - j; } else { return -1; } } }
class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { vector<int> next(lenb,0); getNext(next, B); int i=0,j=0; while(i<lena && j<lenb) { if(j==-1 || A[i]==B[j]){ i++; j++; }else j = next[j]; } if(j == lenb) return i-j; else return -1; } void getNext(vector<int> &next, const string s){ int l = s.length(); next[0] = -1; int k=-1,i=0; while(i < l-1){ if(k==-1 || s[i]==s[k]) { if(s[++i] == s[++k]) next[i] = next[k]; else next[i] = k; }else k = next[k]; } } };
public int findAppearance(String A, int lena, String B, int lenb) { char[] AA = A.toCharArray(); char[] BB = B.toCharArray(); int f = -1; int b = 0; if(lena>=lenb){ for(int a=0;a<lena;a++){ while(b<lenb){ if(BB[b]!=AA[a]){ if((lena-a)<=(lenb-b)){//若剩余的a字符数组小于b数组 return -1; } if(f<0){ break; }else{ if(BB[0]==AA[a]){ f=a; if(lenb==1){ return f; } b=1; }else{ b=0; } break; } } if(BB[b]==AA[a]){ f=a; if(b==(lenb-1)){ return f-lenb+1; } b++; break; } } } } return -1; }
35ms,709k,写的有点麻烦了。。。
最简单的方法:使用STL算法,不过这种方法在面试时不吃香,毕竟体现不出逻辑分析过程。写完整算法过程,最好分A字符串和B字符串的长度大小比较情况进行编码。
//KMP匹配算法 import java.util.*; public class StringPattern { public int findAppearance(String A, int lena, String B, int lenb) { // write code here return kmp(A,lena,B,lenb); } public int kmp(String A,int lena,String B,int lenb){ if(A==null||B==null||lena==0||lenb==0) return -1; int[] next = new int[lenb]; makenext(B,next); int j = 0; for(int i=0;i<lena;i++){ while(j>0&&A.charAt(i)!=B.charAt(j)) j = next[j-1]; if(A.charAt(i)==B.charAt(j)) j++; if(j==lenb) return i-j+1; } return -1; } public void makenext(String B,int[] next){ //创建next表 next[0] = 0; int j = 0; for(int i=1;i<B.length();i++){ while(j>0&&B.charAt(i)!=B.charAt(j)) j = next[j-1]; if(B.charAt(i)==B.charAt(j)) j++; next[i] = j; } } }
/* * @description 字符串匹配的KMP算法; * @author snow * @time 2016-08-07 21:45 * @算法思想:字符串匹配逐项匹配时间复杂度过高,使用KMP算法时间复杂度为O(N); * 每次不用再退回主串进行匹配,模式串返回的位置有最优解,提高了查询效率; */ public class StinrgFitKMP { private static int getSubIndex(char[] cs,char[] ct){ int next[] = new int[ct.length]; int j=0,k=0; next = setNext(next,ct); for(;k<cs.length;k++){ if(j==ct.length) break; if(cs[k]==(ct[j])){ j++; }else if(j!=0){ j = next[j]; k--; } }//for end if(k==cs.length&&j!=ct.length) return -1; return k-j; }//getSubIndex() end //设置next数组,以备出现不匹配时进行字符跳转 private static int[] setNext(int[] next, char[] ct) { next[0] = 0; if(ct.length>1){ next[1] = 0; for(int i=2;i<ct.length;i++){ int p = next[i-1]; /* * 检测i这个位置的前一个信息和next对应的信息; * 相同,则将高处存储为对应的上边的下一个位置; * 不同,则应该只返回上一个对应的位置; * */ while(true){ //虽然嵌套了循环,但是模式串短,并且循环次数和模式串的长度不是同一个数量级,不会影响到时间复杂度的数量级 if(p==0||ct[i-1]==ct[p]){ next[i] = p + 1; break; }else{ p = next[p]; //出现不同,又不是起点,从上一个相关处回执 } }//while end }//for end }//if end return next; }//setNext() end }
}