• luogu:hash专题题解


    T1 :

    运用hash,将每一个字符串储存到(a_1)~(a_n)这个数组中

     ll ans=0,len=strlen(chr);
     for(int i=0;i<len;i++)
         ans=(ans*base+(ll)chr[i])%mod;
     return ans;
    

    然后对(a)排下序
    判断:若后一个和前一个不同的话,记数
    题目链接:洛谷P3370【模板】字符串哈希


    T2 :

    这题可以使用map进行操作
    (vi[])代表使用过了,(vis[])代表出现过,使用(num)进行记数

      if(vis[s] && !vi[s]) {
          vi[s]=1;
          num++;
      }
    

    (num)求出来就是文章中最多包含的要背的单词数
    (v[])代表这个单词出现次数

      if(!v[s]) cnt++;//以前没出现cnt++
      v[s]++;//出现次数++
      while(!vis[a[head]] || (head<i && v[a[head]]>1)) {//不用背或者出现了>1次
          v[a[head]]--;
          head++;
      }
      if(cnt==num) ans=min(ans,i-head+1);
    

    最后输出(ans)即可
    题目链接:P1381 单词背诵


    T3 :

    若n为偶数,直接输出“NOT POSSIBLE”
    然后(n/=2)
    先将前((n/2-1))位读入,然后再读入后((n/2))位
    接着,分情况讨论:

    1. (a[0]!=b[0]),(ans)这个字符串取后半段
      对前半段和(ans)进行比对,如果有(>=2)个字符对应不上即可输出“NOT POSSIBLE”
      代码片段如下:
      for(int i=0,tot=0; i<=n && tot<n; i++)
          if (str[i]==ans[tot])
              tot++;
      if (tot!=n) {
          printf("NOT POSSIBLE");
          return 0;
      }
    
    1. (a[0]==b[0]),(ans)这个字符串取前半段
      对后半段和(ans)进行比对,如果有(>=2)个字符对应不上即可输出“NOT POSSIBLE”
      原理同上,不再多写

    再者,前面已经证明有解了,现在再看看前后两段是否对的上,如果对不上,说明有2个及以上的解,输出“NOT UNIQUE"

      if(str[0] == str[n] && str[0] == str[2 * n]) {
        for(int i = 1; i <= 2 * n; i++)
          if(str[i] != str[i - 1]) {
            printf("NOT UNIQUE");
            return 0;
          }
      }
    

    最后,全部都检查完毕,可以直接输出ans这个字符串
    题目链接:LOJ #2823. 「BalticOI 2014 Day 1」三个朋友


    T4:

    STL大法好
    好吧,我用了(<cstring>)库中的(substr),
    用处是复制子字符串,要求从指定位置开始,并具有指定的长度
    核心代码如下:

      for(int i=0; i<=DNA.length()-k; i++) {
        int h=Hash(DNA.substr(i, k));
        m[h]++;
        ans=max(ans,m[h]);
      }
    

    题目链接:LOJ #537.「LibreOJ NOIP Round #1」DNA序列


    T5:

    枚举每一个状态,找到了就打上(flag)
    子函数:

      ll get_hash(int l,int r) {
          return (h[r]-h[l-1]*pw[r-l+1])%mod;
      }//要用到课上讲的get_hash
      void work(ll* f,int* fl,int* k,int* l,int *r)
      {
          if(*f==0) *f=get_hash(*l,*r);
          else if(*f!=get_hash(*l,*r)) {
            *k=1;
            *fl=1;
          }
      }
    

    我们定义(h0,h1)为'0','1'代表的子串的hash值,p为'1'子串的长度,(l,r)为当前位置,(fl)为当前循环过程是否失败。
    然后直接枚举所以可能值
    核心判断部分 :

    for(int j=0;j<lena;j++) {
      int k=0;
      l=r+1;
      if(a[j]=='0'){
        r+=i;
        work(&h0,&fl,&k,&l,&r);
        if(k) break;
      }
      if(a[j]=='1'){
        r+=p;
        work(&h1,&fl,&k,&l,&r);
        if(k) break;
      }
    }        
    

    判断a,b是否是相同的串,并更新答案:
    最后输出

      if(h0==h1) continue;//若0,1的hash值相等,直接continue
      if(!fl) ans++;
    

    题目链接:洛谷CF1056E Check Transcription


    T6 :

    看了看数据范围:$ n<=50 $
    可以暴力
    核心部分 :

     if(a[i1][j1]==b[i2][j2])
       f[i1][j1][i2][j2]=min(f[i1-1][j1-1][i2-1][j2-1],min(f[i1][j1-1][i2][j2-1],f[i1-1][j1][i2-1][j2]))+1;
     ans=max(ans,f[i1][j1][i2][j2]);
    

    复杂度O((n^4))
    dp+暴力 轻松水过
    题目链接:洛谷P4398 [JSOI2008]Blue Mary的战役地图


    T7:

    dp,然而并不需要hash
    (f[i][j])表示分别以(a[i],b[j])结尾的最长的相同部分的子串的长度。
    (n^2)地枚举i,j,若(a[i]=b[j],f[i][j]=f[i-1][j-1]+1),否则,(f[i][j]=f[i-1][j-1])
    从i=1开始计数,否则会有负质数
    题目链接:洛谷P2957 [USACO09OCT]Barn Echoes G

  • 相关阅读:
    AirtestIDE这个隐藏的小助手,还没用过你就亏啦!
    不懂抓包也能做APP爬虫?1招教你爬取抖音流行歌名
    巧用bat文件做Airtest脚本的“批量运行”
    AirtestIDE1.2.4、1.2.5新版来袭!新增自动更新、iOS更多版本支持...
    NodeService Ensure that Node.js is installed and can be found in one of the PATH directories
    NET CORE通过NodeService调用js
    Java8 的 Stream API 的确牛X,但性能究竟如何呢?
    Java 生成二维码实战
    Java高并发之设计模式,设计思想
    NullPointerException 的处理新方式,Java14 真的太香了!
  • 原文地址:https://www.cnblogs.com/Wuzhuoming-sirenboke/p/13599336.html
Copyright © 2020-2023  润新知