zoukankan      html  css  js  c++  java
  • 字符串的小伙伴

    字符串小朋友结交了很多好朋友,他们大多都很乐于助人,帮助字符串解决他的问题

    一.字符串哈希

      字符串渴望和整数交好朋友,哈希是一个连接字符串和整数之间的媒介,他可以把字符串和整数相互匹配。哈希是多少?当然这个是要做题的人自己来设置的。

      求一个字符串前缀哈希的公式是:hash【i】=(1ll *hash【i-1】*p+idx(s【i】))%mod;

      其中p自己设为一个六位或八位的素数,mod取1e9+7或者+9,idx(s[i])=s[i]-'a'

      现在咱来讲一下怎么求一个子串的hash,公式是:hash[L...R]=((hash[R]-hash[L-1]*(p的R-L+1次方))%mod+mod)%mod

      常用的几个字符串哈希法:1 unsigned long long hash[N] hash[i]=hash[i-1]*自动取模

                  2 单哈希

                  3 双哈希,用pair<hash1,hash2>表示一个字符串mod1=1e9+7,mod2=1e9+9

    哈希的应用:

    1 求s1是不是s2的子串,且在s2中出现了几次

    2 求s1和s2的最大公共子串

    3 求一个字符串里的最长回文字符串

    4 一系列操作后求字典序最小的表示法

    哈希代码如下:

    //用单hash表示字符串前缀
    //并且判断s1在s2中出现了几次
    void hashbuild(int n1,int n2){
        for(int i=1;i<=n1;i++){
            hash1[i]=(1ll*hash1[i-1]*p+s1[i]='a')%mod;
        }
        for(int i=1;i<=n2;i++){
            hash2[i]=(1ll*hash2[i-1]*p+s2[i]-'a')%mod;
        } 
        for(int i=1;i<=n2;i++){
            fp[i]=pow(p,i);
        }
        for(int i=n1;i<=n2;i++){
            if((hash2[i]-1ll*hash2[i-n1]*fp[n1]%mod+mod)%mod==hash[n1])ans++;
        }
    }
    
    hash 1

    //用单hash表示字符串前缀
    //并且判断s1在s2中出现了几次
    void hashbuild(int n1,int n2){
        for(int i=1;i<=n1;i++){
            hash1[i]=(1ll*hash1[i-1]*p+s1[i]='a')%mod;
        }
        for(int i=1;i<=n2;i++){
            hash2[i]=(1ll*hash2[i-1]*p+s2[i]-'a')%mod;
        } 
        for(int i=1;i<=n2;i++){
            fp[i]=pow(p,i);
        }
        for(int i=n1;i<=n2;i++){
            if((hash2[i]-1ll*hash2[i-n1]*fp[i]%mod+mod)%mod==hash[n1])ans++

    二.KMP算法

    用来看s1是不是s2的子串

    next是前缀后缀相同部分最大值

    next:AAA

    位置   0 1 2

    j=       1 2 3

    next   -1 0 1

    注意第i个位置看前i-1个,且不要算自己

    next值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀。例如如果next [j] = k,代表j 之前的字符串中有最大长度为k 的相同前缀后缀。

    KMP算法

    假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置

    • 如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
    • 如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。
        //优化过后的next 数组求法  
        void GetNextval(char* p, int next[])  
        {  
            int pLen = strlen(p);  
            next[0] = -1;  
            int k = -1;  
            int j = 0;  
            while (j < pLen - 1)  
            {  
                //p[k]表示前缀,p[j]表示后缀    
                if (k == -1 || p[j] == p[k])  
                {  
                    ++j;  
                    ++k;  
                    //较之前next数组求法,改动在下面4行  
                    if (p[j] != p[k])  
                        next[j] = k;   //之前只有这一行  
                    else  
                        //因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]  
                        next[j] = next[k];  
                }  
                else  
                {  
                    k = next[k];  
                }  
            }  
        }  
        
    返回值是s1在s2中出现的位置
    int KmpSearch(char* s, char* p) { int i = 0; int j = 0; int sLen = strlen(s); int pLen = strlen(p); while (i < sLen && j < pLen) { //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++ if (j == -1 || s[i] == p[j]) { i++; j++; } else { //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j] //next[j]即为j所对应的next值 j = next[j]; } } if (j == pLen) return i - j+1; else return -1; }

      

  • 相关阅读:
    CSS cursor 属性笔记
    sql 不等于 <>
    去掉时间中的时分秒
    ref 和 out区别
    关于闭包(未完待续)
    面向对象——多态(摘)
    SQL Service 数据库 基本操作 视图 触发器 游标 存储过程
    遍历winform 页面上所有的textbox控价并赋值string.Empty
    关于Html 和Xml 区别(备忘)
    python之面向对象进阶
  • 原文地址:https://www.cnblogs.com/SUMMER20020929/p/9806278.html
Copyright © 2011-2022 走看看