设为首页 加入收藏

TOP

HDU 4821 String 字符串哈希
2015-07-20 18:05:02 来源: 作者: 【 】 浏览:2
Tags:HDU 4821 String 字符串 哈希

?

题意:给出M和L,和一个字符串S。要求找出S的子串中长度为L*M,并且可以分成M段,每段长L,并且M段都不相同的子串个数。

思路:一道字符串哈希题。哈希的方法是BKDRHash,哈希中进制是31,131等素数,(我还以为这是我自己想出来的哈希方法,原来不是,而且进制也不是我选择的26,而是31这样的素数。)

从len-1开始哈希,Hash[i]=Hash[i+1]*SEED+(ss[i]-'a'+1)。O(n)内计算出整个长串的哈希值。在其中长为L的子串的哈希值是Hash[i]-Hash[j+L]*K[L]。

由于M*L<=10^5,所以在检索过程中复杂度最多是O(M*L)。比赛中想到了一种O(M*L)的写法,不过姿势不够优美,挂掉了。优美的姿势是用unsigned long long 的map映射每段长度L的哈希值,用P.size()记录共出现了多少种不同哈希值,如果P.size()=M,则出现了一种符合题意的子串。

在哈希过程中unsighed long long 范围是0~18446744073709551615,并且会自动取模,所以在哈希过程中不需要%MOD这样的出现了。

资料:https://www.byvoid.com/blog/string-hash-compare/

代码:

?

#include
  
   
#include
   
     #include
    
      #include
     
       #include
       #include
       
         #include
        
          #include
         
           #include
          
            #include
           
             #include
            
              #include
             
               #define PI acos(-1.0) #define maxn 10005 #define INF 0x7fffffff #define SEED 31 typedef long long LL; typedef unsigned long long ULL; using namespace std; map < ULL , int > P; ULL Hash[100005]; ULL K[100005]; int main() { int M,L; char ss[100005]; while(scanf(%d%d,&M,&L)!=EOF) { ULL tt=1; scanf(%s,ss); int len=strlen(ss); ULL res=0; Hash[len]=0; K[0]=1; for(int i=1; i<=L; i++) K[i]=K[i-1]*SEED; for(int i=len-1; i>=0; i--) { Hash[i]=Hash[i+1]*SEED+(ss[i]-'a'+1); } int t=0,aa=0; for(int i=0; i
              
               

?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇hdu 4601 Letter Tree 2013多校1-2 下一篇Challenge-2.1.4 部分和问题

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: