旋转字符串的判断——KMP实现 (C++)
2015-12-06 19:37
316 查看
题目:
给定2个字符串srt1和str2,实现一个算法判断其是否互为旋转字符串。
注:
比如字符串"ABCDE" 那么"BCDEA" "CDEAB" "DEABC" "EABCD"都是其旋转字符串。
思路:
这里我们判断str2是否是str1的旋转字符串。
①. 如果str1和str2的长度都不相等,那么肯定返回false,不需要执行下面的操作。
② . str1和str2的长度相等
我们可以按照旋转字符串的定义,对str2进行旋转移位,并判断移位后的字符串是否与str1相等。这样最多需要执行n-1次这样的操作。【n是给定字符串的长度】
下面给出另外一种O(N)复杂度的算法,基于KMP的字符串模式匹配。
举例说明:对于str1 = "ABCD" str2 = "BCDA"
那么 新生成一个新字符串str3 = str1 + str1; 可以看到:
str3 = "ABCDABCD" 这其中包含了所有可能的旋转字符串 即: BCDA CDAB DABC
因此 接下来的操作就是判断str3中是否str2这样的子串,属于字符串匹配问题。可以由KMP算法求解。
贴代码:
给定2个字符串srt1和str2,实现一个算法判断其是否互为旋转字符串。
注:
比如字符串"ABCDE" 那么"BCDEA" "CDEAB" "DEABC" "EABCD"都是其旋转字符串。
思路:
这里我们判断str2是否是str1的旋转字符串。
①. 如果str1和str2的长度都不相等,那么肯定返回false,不需要执行下面的操作。
② . str1和str2的长度相等
我们可以按照旋转字符串的定义,对str2进行旋转移位,并判断移位后的字符串是否与str1相等。这样最多需要执行n-1次这样的操作。【n是给定字符串的长度】
下面给出另外一种O(N)复杂度的算法,基于KMP的字符串模式匹配。
举例说明:对于str1 = "ABCD" str2 = "BCDA"
那么 新生成一个新字符串str3 = str1 + str1; 可以看到:
str3 = "ABCDABCD" 这其中包含了所有可能的旋转字符串 即: BCDA CDAB DABC
因此 接下来的操作就是判断str3中是否str2这样的子串,属于字符串匹配问题。可以由KMP算法求解。
贴代码:
<span style="font-size:14px;">#include <iostream> #include <string> #include <vector> using namespace std; bool chkRotation(const string A, const int lena, const string B, const int lenb); void nextArr(const string str, vector<int> &v); int KMP(const string str, const string mode); bool chkRotation(const string A, const int lena, const string B, const int lenb) { return (KMP(A + A, B) != -1); } // 求next数组v void nextArr(const string str, vector<int> &v) { // 字符串长度为1 直接返回 [-1] if (str.length() == 1) { v[0] = -1; return; } // 前两个字符的next值分别为 -1 0 v[0] = -1; v[1] = 0; unsigned int pos = 2, cnt = 0; while(pos < v.size()) { if (str[pos - 1] == str[cnt]) { v[pos++] = ++cnt; } else if(cnt > 0) { cnt = v[cnt]; } else { v[pos++] = 0; } } } int KMP(const string str, const string mode) { // 异常检查 if (str.empty() || mode.empty() || mode.length() < 1 || str.length() < mode.length()) { return -1; } // next数组长度只与模式串有关 vector<int> next(mode.length()); // 获取next数组 nextArr(mode, next); unsigned int idx = 0, modeIdx = 0; while(idx < str.length() && modeIdx < mode.length()) { if (str[idx] == mode[modeIdx]) { idx++; modeIdx++; } else if (next[modeIdx] == -1) { idx++; } else { modeIdx = next[modeIdx]; } } return ((modeIdx == mode.length()) ? (idx - modeIdx) : -1); } int main(void) { string s1 = "1234", s2 = "2341"; int len1 = s1.length(), len2 = s2.length(); if (chkRotation(s1, len1, s2, len2)) { cout<<"YES : s1 and s2 are rotated string"<<endl; } else { cout<<"NO : s1 and s2 are not rotated string"<<endl; } return 0; }</span>输出:
相关文章推荐
- VS C++执行DOS命令
- C/C++经典面试题(持续更新)
- Java & C++ 数组声明和使用语法对比
- c++_1: 基础问题
- PY++ 自动将你的C++程序接口封装供python调用
- 《C++ primer plus》:类的自动转换和强制类型转换
- C/C++检测进程是否被调试
- POJ3295——Tautology
- c++ 虚表
- 单链表(c语言版)
- Arduino 平台与C语言程序设计-week1-Arduino Environment-Lesson3
- C++学习知识点总结(1)
- c++动态联编与静态联编
- 在Sublime Text 3中配置编译和运行C++程序
- 写给一位期望做得更好的大学生
- C++学习笔记33——友元
- Arduino 平台与C语言程序设计-week1-Arduino Environment-Lesson2
- 【转】C++中struct与class的区别
- C++中多线程Singleton的实现
- C++ inline 函数