zoukankan      html  css  js  c++  java
  • 字符串hash暴力串串题

    我们通过类似进制的方法对字符串hash,可以得到类似前缀和的性质,可以快速得到子串的hash值
    而hash值和字符串是一一对应的(不考虑哈希冲突),因此可以比较和统计

    Leetcode 28. 实现 strStr()

    题意:字符串查找
    方法:用字符串哈希代替KMP

    class Solution {
    public:
        typedef long long ll;
        typedef unsigned long long ull;
        const ull base = 233;
        vector<ull>p, h;
    
        void init(string s)
        {
            ll n = s.size();
            p.resize(n+1, 1);
            h.resize(n+1, 0);
    
            for(int i=1;i<=n;i++)  h[i] = h[i-1]*base + (ull)s[i-1];
            for(int i=1;i<=n;i++)  p[i] = p[i-1]*base;
        }
    
        inline ull gethash(int l,int r)  // 计算第l个 到第r的hash值
        {
            return h[r] - h[l-1]*p[r-l+1];
        }
    
        int strStr(string haystack, string needle) {
            if(needle == "")  return 0;
            ull target = 0;
            for(char ch : needle) target = target*base + (ull)ch;
    
            init(haystack);
            int n = haystack.size(), m = needle.size();
            int i = 1, j = m;
            while(j <= n) {
                // cout << gethash(i, i+m-1) << " " << target << endl;
                if(gethash(i, j) == target)  return i-1;
                i++;j++;
            }
            return -1;
        }
    };
    

    Leetcode 49. 字母异位词分组

    题意:将属于相同排序的字符串放到一起
    方法:将单词sort之后在hash,hash值相同的放一起(其实sort之后没必要hash了...)

    class Solution {
    public:
        int hash(string s)
        {
            unsigned int res = 0;
            unsigned int base = 233;
            sort(s.begin(), s.end());
            for(char ch : s)
                res = res*base + ch;  // 自然溢出
            return (int)res;
        }
    
        vector<vector<string>> groupAnagrams(vector<string>& strs) {
            unordered_map<int, vector<string>>mp;
            for(string s : strs)
                mp[hash(s)].push_back(s);
            vector<vector<string>>ans;
            for(auto it = mp.begin(); it != mp.end();it++)
                ans.push_back(it->second);
            
            return ans;
        }
    };
    

    Leetcode 336.回文对

    题目:求不同的两个单词拼成的回文对
    方法:如果正反哈希值相同,则认为是回文的。预处理所有单词的正反哈希值,可以O(1)得到拼接后的正反哈希值

    class Solution {
    public:
        typedef long long ll;
        typedef unsigned long long ull;
        const ull base = 233;
    
        ull getHash(string& s, int n) {
            ull hash = 0;
            // int n = s.size();
            for(int i = 0;i < n;i++)  hash = hash*base + s[i]-'a';
            return hash;
        }
        ull getRHash(string& s, int n) {
            ull hash = 0;
            // int n = s.size();
            for(int i = n-1;i >= 0;i--)  hash = hash*base + s[i]-'a';
            return hash;
        }
    
        vector<vector<int>> palindromePairs(vector<string>& words) {
            int n = words.size();
            // hs.resize(n);
            // rhs.resize(n);
            // mul.resize(305);  // resize会超时
            ull hs[n], rhs[n], len[n];
            ull mul[305];
            for(int i  = 0;i < n;i++) {
                len[i] = words[i].size();   // 避免每次去求size,也是一个常数级优化 1036ms->568ms
                hs[i] = getHash(words[i], len[i]);
                rhs[i] = getRHash(words[i], len[i]);
            }
            for(int i = 0;i < 305;i++)  mul[i] = (i==0?1:mul[i-1]* base);
    
            vector<vector<int>>ans;
            for(int i = 0;i < n;i++) {
                for(int j = 0;j < n;j++) {
                    if(i == j)  continue;
                    ull left = hs[i]*mul[len[j]] + hs[j];
                    ull right = rhs[i] + rhs[j]*mul[len[i]];
                    if(left == right)  ans.push_back({i,j});
                }
            }
            return ans;
        }
    };
    

    Leetcode 214. 最短回文串

    题目:在字符串前面添加最少的字母,使其变成一个回文串
    方法:找到最长的回文前缀,要补的就是最少的。枚举每个前缀,用hash判断是否回文。

    class Solution {
    public:
        typedef unsigned long long ull;
        ull base = 233;
        string shortestPalindrome(string s) {
            if(s=="") return "";
            int n = s.size(), pos;
            ull hs = 0, rhs = 0, mul = 1;
            for(int i = 0;i < n;i++) {
                hs = hs*base + s[i]-'a';
                rhs = rhs + (s[i]-'a')*mul;
                mul *= base;
                if(hs == rhs)  pos = i;
            }
            string tmp = s.substr(pos+1);
            reverse(tmp.begin(), tmp.end());
            return tmp+s;
        }
    };
    
  • 相关阅读:
    centos6.8安装DB2 10.5
    linux yum配置本地iso镜像
    DB2的空间数据库管理复杂配置
    高性能计算linux集群常用配置
    centos 6.8操作系统安装arcgis server 10.4
    【转】用python实现简单的文本情感分析
    Python3制作中文词云图
    MongoDB Replica Set搭建集群
    pycharm编写spark程序,导入pyspark包
    Mysql变量声明与使用
  • 原文地址:https://www.cnblogs.com/lfri/p/15732019.html
Copyright © 2011-2022 走看看