字符串匹配算法
来源:互联网 发布:cookie的js代码调用 编辑:程序博客网 时间:2024/06/05 10:23
字符串匹配算法
- 字符串匹配算法
- 朴素字符串匹配算法
- Rabin-Karp算法
- 有限自动机算法
- KMP算法
- 笔面高频题
- 单词间的逆序调整
- 前n字符后移
- 两字字符按照字典序最小拼接
- 判断两个字符串是否互为旋转词
朴素字符串匹配算法
//朴素字符串匹配算法(输出偏移量)/* * 朴素字符串匹配算法是通过一个循环找到所有有效偏移,该循环对n-m+1可能的s值进行检测, * n是要在上面进行查找的对象大小,m是所要查找的目标的大小,s是偏移量。 * 朴素字符串匹配算法的匹配时间为O((n-m+1)*m) * */void nativeStringMatchar(string str, string com){ for(int i = 0; i <= int(str.length()-com.length()); i++){ bool judge = true; for(int j = 0; j < int(com.length()); j++){ if(str[j+i] != com[j]){ judge = false; break; } } if(judge) cout << i << ' '; }}
Rabin-Karp算法
//Rabin-Karp算法/* * 字符串 * n = 12345678 * m = 1234 * lm = m.length() * * 步骤: * 1.预处理: * 预处理就是计算出字符串m的哈希值,我们计算哈希值的算法就是把这些字符关联在一个多项式里面, * 多项式的模式就是 m[0]*x^lm-1 + m[1]*x^lm-2 + .... + m[lm-1]*x^0 这种形式的,这样就把一串字符关联在了一个多项式里面, * 然后我们利用霍纳法则优化多项式的计算,这样的话,我们可以在O(m)时间内,计算出字符串的哈希值 * * 2.搜索 * 搜索的话就是从字符串n里面第一个lm长的字符串开始,不断地比较这个字符串与字符串m的哈希值,如果哈希值相等的话, * 就再去一个字符一个字符的比较一下是否相等,这样,我们最快,可以在O(n-m+1)的时间内比较完,最坏的情况是O((n-m+1)*m) * 但是平均时间来看,rk算法要比朴素算法快得多 * * 关键点: * 1.哈希算法的关键,就是计算关联这一串字符串的多项式,每个字符值都是多项式的一个系数 * 2.利用霍纳法则优化多项式的计算 * 3.如果明白了哈希值的计算是多项式相加的结果,就不难明白计算n字符串里面其余lm长度字符串大小的哈希值的算法了 * * */ void rabinKarp(string str, string com){ int hStr = 0, hCom = 0; int lCom = com.length(); int lStr = str.length(); int d = (1<<(lCom-1));//多项式第一项的系数,x^m-1 //预处理(使用霍纳法则进行优化多项式的运算) for(int i = 0; i < lCom; i++){ hStr = (hStr<<1) + str[i]; hCom = (hCom<<1) + com[i]; } //搜索 for(int i = 0; i <= lStr - lCom; i++){ if(hStr == hCom){ bool judge = true; for(int j = 0; j < lCom; j++){ if(str[i+j] != com[j]){ judge = false; break; } } if(judge) cout << i << ' '; } //计算下一个模式的哈希值,思路就是去掉第一个字符的多项式的值,加上新加的字符的多项式的值 if(i != lStr-lCom) hStr = ((hStr-str[i]*d)<<1) + str[i+lCom]; } } /* * 当Rabin-karp算法中字符串的哈希值过大时,出现问题就是我们不能在用常数的时间去计算一个字符串的哈希值, * 解决方法就是利用每个哈希值都对一个数取模解决,这样数就能变小了, * 但是还有一个问题是,并不是所有模相等的数都相等,但是模不相等的数肯定不相等,这样就会出现很多伪命中点, * 所以,我们只能用这个方法来判断是否不相等,相等时的误差率会增大 * * */ void rabinKarpForBig(string str, string com){ int hStr = 0, hCom = 0; int lCom = com.length(); int lStr = str.length(); int q = 13; int d = (1<<(lCom-1))%q;//多项式第一项的系数,x^m-1 //预处理(使用霍纳法则进行优化多项式的运算) for(int i = 0; i < lCom; i++){ hStr = ((hStr<<1) + str[i])%q; hCom = ((hCom<<1) + com[i])%q; } //搜索 for(int i = 0; i <= lStr - lCom; i++){ if(hStr == hCom){ bool judge = true; for(int j = 0; j < lCom; j++){ if(str[i+j] != com[j]){ judge = false; break; } } if(judge) cout << i << ' '; } //计算下一个模式的哈希值,思路就是去掉第一个字符的多项式的值,加上新加的字符的多项式的值 if(i != lStr-lCom){ hStr = (((hStr-str[i]*d)<<1) + str[i+lCom])%q; if(hStr < 0) hStr += q; } }}
有限自动机算法
//构建转移函数二维表void makeJumpTable(string p){ int m = p.length(); int alphaSize = 4; for(int q = 0; q <= m; q++) for(int k = 0; k < alphaSize; k++){ char c = (char)('1' + k); string Pq = p.substr(0, q) + c; int nextState = findSuffix(Pq, p); cout << "from state " << q << " receive input char " << c << " jump to state " << nextState << endl; map<char, int> m = jumpTable[q]; m[c] = nextState; jumpTable[q] = m; }}int match(string T, string p){ int q = -1; for(int n = 0; n <= int(T.length()); n++){ map<char, int> m = jumpTable[q]; int oldState = q; q = m[T[n]]; if(q == -1) return -1; cout << "In state " << oldState << " receive input " << T[n] << " jump to state " << q << endl; if(q == int(p.length())) cout << n << ' '; } return -1;}
KMP算法
//KMP算法int Pi[500];//找最长后缀大小int getLongestSuffix(int s, string P) { if(s <= 0 || s > int(sizeof(Pi)/4)) return -1; if(Pi[s] != -2) return Pi[s]; Pi[s] = 0; int k = getLongestSuffix(s-1, P); do{ if(P[k] == P[s-1]) return Pi[s] = k + 1; if(k > 0) k = getLongestSuffix(k, P); }while(k > 0); return Pi[s];}int KMP(string T, string P) { int m = P.length(); for(int i = 0, q = 0; i < int(T.length()); i++) { //如果遇到一个不相等的,就往后移,移动的长度就是我们找到的最长后缀大小,直到找到一个相等的 while(q > 0 && P[q] != T[i]) q = Pi[q]; //如果遇到相等的,就继续 if(P[q] == T[i]) q = q + 1; //当相等的个数为待匹配字符时,ok,说明包含 if(q == m) return i-m+1; } return -1;}
笔面高频题
单词间的逆序调整
//单词间的逆序调整//思路:逆序遍历一遍字符串,遇到空格就输出单词,把第一个和最后一个特殊情况处理一下就ok了string wordInvert(string str){ string result; int end; end = str.length(); for(int i = str.length(); i >= 0; i--){ if(str[i] == ' ' || i == 0) { if(i != 0) result += str.substr(i+1, end-i-1); else result += str.substr(i, end-i+1); if(i != 0) result += " "; end = i; } } return result;}void invert(string& str, int start, int end){ int len = end - start + 1; for(int i = start; i < start + len/2; i++){ char tmp = str[i]; str[i] = str[start+len-(i-start)-1]; str[start+len-(i-start)-1] = tmp; }}
前n字符后移
//将前index个字符移到后面//思路,整体逆序,然后再部分逆序string wordInvert(string str, int index){ invert(str, 0, str.length()-1); invert(str, 0, str.length()-index-2); invert(str, str.length()-index-1, str.length()-1); return str;}
两字字符按照字典序最小拼接
//将两个给定的字符串按照最小字典序进行拼接string wordJoin(string one, string two){ string tOne = one+two, tTwo = two+one; int lOne = int(tOne.length()), lTwo = int(tTwo.length()); int len = lOne > lTwo ? lOne : lTwo; for(int i = 0; i < len; i++){ //如果短的字符串是长的字符串的前缀的话,就返回短的字符串 if(lOne < i+1 && lTwo >= i+1) return tOne; else if(lTwo < i+1 && lOne >= i+1) return tTwo; else if(lTwo == lOne && lTwo == i+1) return tTwo; //如果一个字符串的某个字符小于另一个,则小 else if(tOne[i] < tTwo[i]) return tOne; else if(tOne[i] > tTwo[i]) return tTwo; }}
判断两个字符串是否互为旋转词
//判断两个字符串是否互为旋转词/* * 1.先判断字符串长度是否相等,不相等直接false * 2.字符串长度相等的话,就把其中一个字符串使其自身相加 * 3.把两一个字符串与自身相加的字符串进行kmp算法比较,看看是否包含在其中 * * 关键点:一个字符串自身相加的话,就包含了他自己所有的旋转词 * * */bool judgeRotateWord(string one, string two){ if(one.length() != two.length()) return false; string tmp = one+one; if(KMP(tmp, two)) return true; return false;}
0 0
- 算法 字符串匹配算法
- 字符串匹配算法
- BM字符串匹配算法
- KMP 字符串匹配算法
- 字符串匹配算法
- 字符串匹配算法
- 字符串匹配算法(摘)
- 字符串匹配算法
- 字符串匹配算法
- 字符串匹配的算法
- kmp字符串匹配算法
- 字符串匹配算法
- 字符串匹配算法研究
- 字符串模式匹配算法
- kmp字符串匹配算法
- KMP字符串匹配算法
- 字符串模式匹配算法
- BM字符串匹配算法
- python内置函数5-getattr()
- MYSQL管理之主从同步管理
- Java中的多线程
- linux 任务管理总结
- 深度学习发展历史
- 字符串匹配算法
- 帧动画的简单使用
- override和overload的区别
- HDU
- 如何在 ubuntu 下使用 iNode 客户端
- jpa学习5--spring data jpa 中的JpaSpecificationExecutor和PagingAndSortingRepository分页
- DP——HDU2571:命运(DP)
- MySQL 5.7 安装完成后,立即要调整的性能选项
- oracle创建顺序