赞
踩
- class Solution {
- public:
- int strStr(string haystack, string needle) {
- // 0.异常处理
- if (0 == needle.size()) return 0;
- // 1.初始化准备
- int m = haystack.size();
- int n = needle.size();
- // 2.暴力匹配,[0, m-n]
- for (int i=0; i<=m-n; ++i) {
- int j = 0;
- // 开始匹配
- for (; j<n; ++j) {
- if (needle[j] != haystack[i+j]) break;
- }
- if (j == n) return i;
- }
- return -1;
- }
- };

时间复杂度O(n*m),空间复杂度O(1)
这会使得哈希值比较大,可能出现溢出情况
- class Solution {
- public:
- int strStr(string haystack, string needle) {
- // 0.异常处理
- if (0 == needle.size()) return 0;
- // 1.准备工作
- int m = haystack.size();
- int n = needle.size();
- // 1.1 26^0~26^(n-1)计算存储
- vector<long> powers(n);
- powers[0] = 1;
- for (int i=1; i<n; ++i) {
- powers[i] = powers[i-1] * 26;
- }
- // 1.2 主串哈希值计算,前后字符串有重叠部分,可以利用这个减少计算量
- unordered_map<long, vector<int>> mp; //hash_value -> start_position,拉链法解决哈希冲突
- // 1.2.1 首个子串哈希值计算
- long long hash = 0;
- for (int i=0; i<n; ++i) {
- hash += (haystack[i] - 'a') * powers[n-i-1];
- }
- mp[hash].push_back(0);
-
- // 1.2.2 [1, m-n)范围计算
- for (int i=1; i<=m-n; ++i) {
- hash = (hash - powers[n-1] * (haystack[i-1] - 'a')) * 26 + (haystack[i+n-1] - 'a');
- mp[hash].push_back(i);
- }
-
- // 2.正式处理
- // 2.1 计算needle哈希值
- hash = 0;
- for (int i=0; i<n; ++i) {
- hash += (needle[i] - 'a') * powers[n-i-1];
- }
-
- // 3.返回结果
- if (mp.find(hash) == mp.end()) return -1; //找不到
- return mp[hash][0]; //返回第一个
- }
- };

由于生成哈希值的方式,是唯一的,但是太大了,该代码会产生整数溢出的问题,时间复杂度生成哈希表的时间复杂度是O(m+n),匹配子串复杂度似是O(1),空间复杂度O(m+n)
降低生成哈希值的最大值,比如用字符串的每一个字符从编码相加作为哈希值,虽然会出现比较多的哈希冲突,但是可以避免整数溢出问题,出现哈希冲突就在检查一遍,也就是对哈希值相等的情况再去判断即可
- class Solution {
- public:
- int strStr(string haystack, string needle) {
- // 1.异常处理
- if (needle.size() == 0) return 0;
- // 2.准备工作,主要是生成主串中所有子串长度的字符串的哈希值
- int m = haystack.size();
- int n = needle.size();
-
- unordered_map<int, vector<int>> mp; //拉链法解决冲突
- // 2.1 首个哈希值计算
- int hash = 0;
- for (int i=0; i<n; ++i) {
- hash += (haystack[i] - 'a');
- }
- mp[hash].push_back(0);
-
- // 2.2 剩余[1, m-n]个子串哈希值计算,利用前后字符串的重复部分可以减少计算
- for (int i=1; i<=m-n; ++i) {
- hash = hash - (haystack[i-1] - 'a') + (haystack[n+i-1] - 'a');
- mp[hash].push_back(i);
- }
-
- // 3.匹配子串,注意哈希匹配了还是要检查一遍,因为存放不同的字符串对于相同哈希值的情况
- // 3.1 计算needle哈希值
- hash = 0;
- for (int i=0; i<n; ++i) {
- hash += (needle[i] - 'a');
- }
- // 3.2 开始匹配
- if (mp.find(hash) == mp.end()) return -1;
- // 检查每个结果
- for (auto &i : mp[hash]) {
- int j = 0;
- for (; j<n; ++j) {
- if (needle[j] != haystack[i+j]) break;
- }
- if (j == n) return i; //匹配
- }
- return -1; //虽然哈希值相同,但是全都不匹配
- }
- };

时间复杂度O(n+m),空间复杂度O(n*最大冲突个数)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。