X Tutup
// // Created by 破忆断回 on 2021/9/25. // #include "StringAlgo.h" #include #include #include #include #include #include #include #include using std::cout; using folly::StringPiece; using folly::F14FastSet; using folly::fbstring; using folly::fbvector; inline fbstring StringAlgo::sub_string_range() { fbstring str = "364210432182613"; fbstring target = "321"; int need_match_num = static_cast(target.length());// 需要匹配的数目 if (need_match_num == 0) { return {}; } std::unordered_map map; for (char c: target) { map[c]++; //note 填入表格 } int range_start = 0; int range_end = 0; std::pair result = {0, str.length()}; size_t str_length = str.size(); for (size_t index = 0; index < str_length; index++) { char cur = str[index]; if (bool match_char = map.find(cur) != map.end(); match_char) { map[cur] -= 1; //遇到则直接消除 need_match_num -= 1; } //此次将匹配到所有字符 将确定右侧位置 if (bool get_all_chars = need_match_num <= 0; get_all_chars) { range_end = static_cast (index); // 移动 左侧 将填入相关值 while (range_start < range_end) { auto iterator = map.find(str[range_start]); // note 当前的数据并不是需要匹配的数据 或者 虽说匹配但之后 当前的数据仍有多余 if (iterator == map.end()) { range_start += 1; } else { if (iterator->second < 0) { iterator->second += 1; range_start += 1; } else break; } } if (range_end - range_start < result.second - result.first) { result.first = range_start; result.second = range_end; } } } // note 当前的最后一个元素也应该填入 return {str.begin() + result.first, str.begin() + result.second + 1}; } inline void StringAlgo::all_sub() { // 打印所有的子序列 fbstring data = "12345"; printAll("", 0, data); } inline size_t StringAlgo::exp_n(int n) { std::function imp = [&](int cur) -> size_t { if (cur == 1)return 1l; return cur * imp(cur - 1); }; return imp(n); } void StringAlgo::string_compress() { fbstring data = "12001"; fbstring::size_type len = data.size(); std::array num = {'w', 'q', 'b', 's'}; fbstring result; result.append({data.front(), num[0]}); if (len > 2) { bool find_zero = false; for (int index = 1; index < len; index++) { fbstring::const_reference cur = data.at(index); if (cur != '0') { if (find_zero) { if (index == len - 1) { result.append({'L', cur}); } else { result.append({'L', cur, num[index]}); } find_zero = false; } else { if (index == len - 1) { result.append({cur}); } else result.append({cur, num[index]}); } } else find_zero = true; } } cout << fmt::format("result {}", result); } void StringAlgo::string_expression() { std::array data = {1, 2, 2, 5, 8}; std::function impl = [&](const int index) -> int { size_t len = data.size(); if (index == len) return 1; //都选择完成了当前算一个情况 if (data.at(index) == 0) //当前是一个零 return 0; int result = impl(index + 1);// 当前作为一个字符 if (index + 1 == len) //已经是最后一个字符了 return result; auto concat_value = data.at(index) * 10 + data.at(index + 1); if (index + 1 < len && concat_value < 27) { result += impl(index + 2); } return result; }; cout << impl(0); const auto &dpImpl = [&data](int index) { if (data.at(index) == 0)return 0; size_t len = data.size(); fbvector dp(len + 1); dp[len] = 1; return dp[data.size()]; }; } void StringAlgo::find_longest_not_repeat_sub() { // 找到最长未出现的连续子串 std::array data{}; std::fill(data.begin(), data.end(), -1); fbstring str = R"(assdgdhkasdgftyzxcyt)"; int result_len = 0; int interval = 0; int pre = -1;// 判断当前可以判断的字符起始位置在哪里 fbstring::size_type size = str.size(); //如果以当前字符结尾的情况下 将获得最长的间隔为多少 for (size_t i = 0; i < size; i++) { // 当前的起始位置 要不就是与上一次一致 要不然就是上一次出现当前字符的位置 // 去掉转化str[i pre = std::max(pre, data[static_cast(str[i])]); // 当前可以达到的最大长度为 interval = i - pre; dbg(interval, folly::StringPiece(str.begin() + i + 1 - interval, str.begin() + i + 1), "\n"); result_len = std::max(interval, result_len); data[str[i]] = i; } } void StringAlgo::string_replace() { // 从字符串str1 到 str2 提供 插入 删除 修改的代价为 ic dc rc // 得到最小的代价 fbstring first = "asd"; fbstring second = "aad"; auto dp = fbvector>(first.size() + 1, fbvector(second.size() + 1)); int ic = 5; int dc = 11; int rc = 7; size_t front_size = dp.front().size(); for (size_t i = 0; i < front_size; i++) { dp[0][i] = i * ic; // 从空字符变成当前的字符串 需要多少个插入代价 } size_t row_size = dp.size(); for (size_t i = 0; i < row_size; i++) { dp[i][0] = i * dc; // 从当前的字符串变成空字符 需要多少个删除代价 } fbstring::size_type first_size = first.size(); fbstring::size_type second_size = second.size(); for (size_t x = 1; x < first_size; x++) { for (size_t y = 1; y < second_size; y++) { if (first[x] == second[y]) { // 当前字符相等的情况下 情况与 dp[x-1][y-1]所耗费的代价相同 dp[x][y] = dp[x - 1][y - 1]; } else { dp[x][y] = dp[x - 1][y - 1] + rc;// 否则就是的改一个字符代价 } dbg(dp[x - 1][y] + dc, dp[x][y - 1] + ic, dp[x][y]); dp[x][y] = std::min({dp[x - 1][y] + dc, dp[x][y - 1] + ic, dp[x][y]}); } } } void StringAlgo::boolean_expression() { // 有关当前的 布尔表达式的运算过程 fbstring expression = "1^0|0|1"; std::function impl = [&]( bool desired, int left, int right) -> int { if (left == right) { if (expression[left] == '1') return desired ? 1 : 0; else return desired ? 0 : 1; } int result = 0; if (desired) // 偶数位才是当前的运算符 { for (int i = left + 1; i < right; i += 2) { dbg(desired); dbg(expression[i], folly::StringPiece(expression.begin(), expression.begin() + i)); dbg(folly::StringPiece(expression.begin() + i + 1, expression.begin() + right)); switch (expression[i]) { case '^': result += impl(false, left, right - 1) * impl(true, left + 1, right); result += impl(true, left, right - 1) * impl(false, left + 1, right); break; case '|': result += impl(false, left, right - 1) * impl(true, left + 1, right); result += impl(true, left, right - 1) * impl(false, left + 1, right); result += impl(true, left, right - 1) * impl(true, left + 1, right); break; case '&': result += impl(true, left, right - 1) * impl(true, left + 1, right); break; default: break; } } } else { // 偶数位才是当前的运算符 for (int i = left + 1; i < right; i += 2) { dbg(desired); dbg(expression[i], folly::StringPiece(expression.begin(), expression.begin() + i)); dbg(folly::StringPiece(expression.begin() + i + 1, expression.begin() + right)); switch (expression[i]) { case '^': result += impl(true, left, right - 1) * impl(true, left + 1, right); result += impl(false, left, right - 1) * impl(false, left + 1, right); break; case '|': result += impl(false, left, right - 1) * impl(false, left + 1, right); break; case '&': result += impl(true, left, right - 1) * impl(false, left + 1, right); result += impl(false, left, right - 1) * impl(true, left + 1, right); result += impl(false, left, right - 1) * impl(false, left + 1, right); break; default: break; } } } return result; }; impl(false, 0, expression.size() - 1); } void StringAlgo::expression() { fbstring str1 = "48*((70-65)-43)+8*1"; fbstring str2 = "3+1*4"; struct StrResult { int find_right_bracket; //遇到右括号 或者终止 int end_position; }; auto dfs = [&str1](int start, int cur, auto &&dfs) -> StrResult { fbvector stack(str1.size()); //stack 存储当前的表达式 // 按照当前的进栈规则行进 while (start != str1.size() && str1[start] != '}') { } // stack Manipulate }; } inline void StringAlgo::printAll(const folly::fbstring &cur, size_t index, const folly::fbstring &data) { if (index == data.size()) { cout << cur << '\n'; return; } printAll(cur + data[index], index + 1, data); printAll(cur, index + 1, data); } void StringAlgo::wordBreak() { std::string cur = "pineapplepenapple"; std::unordered_set wordDict{"apple", "pen", "applepen", "pine", "pineapple"}; folly::fbvector rst; std::function can = [&](StringPiece piece, std::string &t) { if (piece.empty()) { rst.emplace_back(t); dbg(t); return; } for (const auto &str: wordDict) { if (piece.startsWith(str)) { t += " " + str; dbg(piece.size(), str.size(), folly::join("", piece), str); can(piece.subpiece(str.length()), t); } } }; std::string tmp; can(cur, tmp); dbg(folly::join("---", rst)); } void StringAlgo::searchWord() { std::array, 4> board = {std::array {'o', 'a', 'a', 'n'}, {'e', 't', 'a', 'e'}, {'i', 'h', 'k', 'r'}, {'i', 'f', 'l', 'v'}}; std::array words{"oath", "pea", "eat", "rain"}; std::array, 4> pos = {std::tuple{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; folly::F14ValueSet rst; int size = board.size(); const auto impl = [&](int x, int y, int count, int wordIndex, auto &&impl) -> void { if (x < 0 || x >= size || y < 0 || y >= size) { return; } if (wordIndex == -1) { for (int i = 0, wordSize = words.size(); i < wordSize; ++i) { const auto &ref = words[i]; if (ref[0] == board[x][y]) { for (auto [xInc, yInc]: pos) { impl(x + xInc, y + yInc, count + 1, i, impl); } } } } else { if (count == words[wordIndex].size()) { rst.insert(wordIndex); } else { } } }; } void StringAlgo::minWindows() { // 76最小覆盖子串 fbstring str{"aa"}; fbstring pattern{"aa"}; int resLen = INT_MAX; int resStart = 0; int left = 0; int right = 0; auto patternSize = pattern.size(); std::unordered_map need; need.reserve(patternSize); for (char a: pattern) { need[a]++; } std::unordered_map windows; windows.reserve(patternSize); auto originSize = str.size(); auto needSize = need.size(); int vailEleCount = 0; //来计算当前有多少个字符匹配成功 while (right < originSize) { char curRightEle = str[right]; right++; if (need.count(curRightEle)) { windows[curRightEle]++; // 如果重复元素进行添加则可能出现 aa +1 +2的情况 // 我们只认定当前 need['a']=2 == windows['a']=2 的情况 if (need[curRightEle] == windows[curRightEle]) { ++vailEleCount; } } while (vailEleCount == needSize) { if (right - left < resLen) { resLen = right - left; resStart = left; } char curLeftEle = str[left]; ++left; if (need.count(curLeftEle)) { if (need[curLeftEle] == windows[curLeftEle]) { --vailEleCount; } windows[curLeftEle]--; } } } auto res = resLen != INT_MAX ? str.substr(resStart, resLen) : fbstring{}; } void StringAlgo::findRepeatedDnaSequences() { fbstring s{"AAAAAAAAAAAAA"}; int sSize = s.size(); std::unordered_set mSet; mSet.reserve(sSize); int cur = 0; const auto curCharNumber = [](char a) { switch (a) { case 'A': return 3; case 'C': return 1; case 'G': return 2; default: return 0; } }; for (int i = 0; i < 10; ++i) { cur = cur * 4 + curCharNumber(s[i]); } mSet.insert(cur); int pow1 = std::pow(4, 9); std::vector res; //这个结构需要去重吗? for (int i = 1; i + 10 <= sSize; ++i) { // 向前一步 则高位去掉一个位 低位添加一位 cur = cur - (curCharNumber(s[i - 1]) * pow1); dbg(cur); cur = cur * 4 + curCharNumber(s[i + 9]); dbg(cur); dbg(mSet); if (! mSet.insert(cur).second) { res.emplace_back(s.substr(i, 10)); } } dbg(res); } void StringAlgo::Rabin_Karp() { fbstring txt; fbstring pattern; auto patternSize = pattern.size(); if (txt.size() < patternSize)return; // 取一个比较大的素数作为求模的除数 int Q = 1658598167; //设计的余数 %Q 作为hash 函数 用于处理可能溢出的结果 int base = 256;// 进制数 long RL = 1; for (int i = 1; i <= patternSize - 1; i++) { // note 这里是 patterSize -1 因为三位数则 需要减掉 二位^base // 计算过程中不断求模,避免溢出 RL = (RL * 256) % Q; } int windowsHash = 0; int left = 0; int right = 0; int patterHash = 0; // 获得模式串的hash值 for (int i = 0; i < patternSize; ++i) { patterHash = ((patterHash * base) % Q + pattern[i]) % Q; } std::unordered_set res; while (right < txt.size()) { windowsHash = ((windowsHash * base) % Q + txt[right]) % Q; //cur*base 后进行加的操作可能会出现溢出的操作所以先处理溢出数 right++; if (right - left == patternSize) { if (windowsHash == patterHash) { // 出现重复的hash 值 //需要进一步判断当前是否发生了 一个hash 值对应多个的情况 if (! std::equal(pattern.begin(), pattern.end(), txt.begin() + left, txt.begin() + right)) { // 没有重复记录当前位置 res.insert(left); } } // X % Q == (X + Q) % Q 是一个模运算法则 // 因为 windowHash - (txt[left] * RL) % Q 可能是负数 // 所以额外再加一个 Q,保证 windowHash 不会是负数 windowsHash = ((windowsHash - txt[left] * RL) % Q + Q) % Q; } left++; } //res; }
X Tutup