• BZOJ4779[Usaco2017 Open]Bovine Genomics


    我首先首先先考虑了二分+hash,但可能是我的二分有点问题,一直tle了一个点,然后完全不知道怎么去改变,只能去USACO的官网上看,结果发现了更厉害的方法。

    原英文题解:http://www.usaco.org/current/data/sol_cownomics_gold_open17.html

    那么我按照我的理解讲一下,首先我们开始定义一个区间lef和righ,开始我们将其全部赋值为0,表示求出lef+1到righ这个区间各个牛的hash值(我是用rand(),不过这个看自己的心情随便赋值吧),然后看看有没有重复的,如果这个区间双方的牛互相没有相同的hash值那么就可以更新答案,同时将lef++,同时每头牛的hash值减去最前面一个字母的hash,然后继续往下做(意思就是如果当前符合答案,那么我们把这个区间的最前面一位去掉,看看是否有更优的答案),如果有相同的hash值,那么说明当前区间还不可以,所以righ++,并将每头牛的hash值加上后面一位的值进行更新。他利用的就是如果当前区间是可行的,那么把它当做后缀的区间也一定是可行的,所以一定会访问到这个可行区间。

    分析了一下,它的hash值计算是从上一次的推出来的,而我之前hash是每次都重新计算一遍,所以。。。

    对了判断hash有无,很方便的可以用set来。

    下面是具体程序:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<set>
    #define maxn 1009
    #define mo 53894320
    using namespace std;
    typedef long long ll;
    char ch[maxn];
    int n,ans,m,t;
    ll val[maxn],s1[maxn][maxn],s2[maxn][maxn],hash1[maxn],hash2[maxn];
    int main()
    {
      scanf("%d%d",&n,&m);
      for (int i=1;i<=n;i++) 
      {
       scanf("%s",ch);
       for (int j=0;j<m;j++) s1[i][j]=ch[j]-65;
      }
      for (int i=1;i<=n;i++) 
      {
       scanf("%s",ch);
       for (int j=0;j<m;j++) s2[i][j]=ch[j]-65;
      }
      for (int i=0;i<m;i++) val[i]=rand()%mo;
      ans=m;t=n;
      int lef=0,righ=0;
      while (righ<m)
      {
           set<ll>p; 
           if (t==0) ans=min(ans,righ-lef);
           if (t>0)
           {
            t=0;
            for (int i=1;i<=n;i++) 
          {
           hash1[i]=(hash1[i]+s1[i][righ]*val[righ])%mo;
           p.insert(hash1[i]);
          }
          for (int i=1;i<=n;i++)
          {
           hash2[i]=(hash2[i]+s2[i][righ]*val[righ])%mo;
           if (p.count(hash2[i])) t++;
          }
          righ++;
         }
         else
         {
          t=0;
          for (int i=1;i<=n;i++) 
          {
           hash1[i]=((hash1[i]-(s1[i][lef]*val[lef]))%mo+mo)%mo;
           p.insert(hash1[i]);
          } 
          for (int i=1;i<=n;i++)
          {
           hash2[i]=((hash2[i]-s2[i][lef]*val[lef])%mo+mo)%mo;
           if (p.count(hash2[i])) t++;
          }
          lef++;
         }
      }
      printf("%d
    ",ans);
      return 0;
    } 
  • 相关阅读:
    最小生成树(Prime算法)
    Spiral Matrix
    大于非负整数N的第一个回文数 Symmetric Number
    毁灭者问题
    查看Centos7虚拟机的IP
    创建Redis集群时遇到问题(二)
    EditPlus通过FTP远程连接Linux
    Redis集群搭建
    创建Redis集群时遇到问题(一)
    安装redis报错“系统 Ruby 版本过低”的解决办法
  • 原文地址:https://www.cnblogs.com/2014nhc/p/7737106.html
Copyright © 2020-2023  润新知