思路:利用Karp-Rabin算法的思想,对每个子串进行Hash,如果Hash值相等则认为这两个子串是相同的(事实上还需要做进一步检查),Karp-Rabin算法的Hash函数有多种形式,但思想都是把字符串映射成一个数字。本题hash函数是把字串转化为NC进制的数(实际上程序中计算结果已经被转换为10进制,因为NC进制数不同转化为10进制数自然不同,所以不影响判断结果),数组开到了1.6×10^7(我试了一下1.2×10^7也能AC),实际上这也是不严谨的,因为我们不能保证hash之后的数值在这个范围内,比如N=NC=35,程序就有Bug了,但是这题后台数据可能没这么给。在实际运用中是需要取模的,而且即使hash值相等也需要进一步比对。


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool hash[16000005];
int is_have[300];
char str[1000005];
int main(){
int n, nc;
/* freopen("in.c", "r", stdin); */
while(~scanf("%d%d", &n, &nc)){
memset(str, 0, sizeof(str));
memset(hash, 0, sizeof(hash));
memset(is_have, 0, sizeof(is_have));
scanf("%s", str);
int len = strlen(str);
int k = 0, ans = 0;
for(int i = 0;i < len;i ++) is_have[str[i]] = 1;
for(int i = 0;i < 256;i ++)
if(is_have[i]) is_have[i] = k++;
for(int i = 0;i <= len - n;i ++){
int key = 0;
for(int j = i;j < i + n;j ++) key = key*nc + is_have[str[j]];
if(!hash[key]) ans ++, hash[key] = 1;
}
printf("%d\n", ans);
}
return 0;
}

下面附上一般情况的实现代码(均来自其他网友):



1. 原文链接:http://www.xefan.com/archives/83853.html

#include <stdio.h>
#include <math.h>
int mod = 0x7fffffff;
const int d = 128;
int rabin_karp(char *T, char *P, int n, int m)
{
if (n < m) return -2;
int h = pow(d, m-1);
int p = 0;
int t = 0;
int i, j;
for (i=0; i<m; i++) {
p = (d*p + P[i]) % mod;
t = (d*t + T[i]) % mod;
}
for (j=0; j<=n-m; j++) {
if (p == t) {
return j;
}
if (j < n-m) {
t = (d*(t - h*T[j]) + T[j+m]) % mod;
}
}
return -1;
} int main(int argc, char *argv[])
{
char t[] = "BBC ABCDAB ABCDABCDABDE";
char p[] = "ABCDABD";
int len1 = sizeof(t) - 1;
int len2 = sizeof(p) - 1;
int index = rabin_karp(t, p, len1, len2);
printf("index: %d\n", index);
return 0;
}

2.原文链接:http://blog.csdn.net/onezeros/article/details/5531354



//Karp-Rabin algorithm,a simple edition
int karp_rabin_search(const char* text,const int text_len,const char* pattern,const int pattern_len)
{
int hash_text=0;
int hash_pattern=0;
int i; //rehash constant:2^(pattern_len-1)
int hash_const=1;
/*for (i=1;i<pattern_len;i++){
hash_const<<=1;
}*/
hash_const<<=pattern_len-1; //preprocessing
//hashing
for (i=0;i<pattern_len;++i){
hash_pattern=(hash_pattern<<1)+pattern[i];
hash_text=(hash_text<<1)+text[i];
} //searching
for (i=0;i<=text_len-pattern_len;++i){
if (hash_pattern==hash_text&&memcmp(text+i,pattern,pattern_len)==0){
return i;
}else{
//rehash
hash_text=((hash_text-text[i]*hash_const)<<1)+text[i+pattern_len];
}
}
return -1;
}

POJ 1200 Crazy Search的更多相关文章

  1. poj 1200 Crazy Search(hash)

    题目链接:http://poj.org/problem?id=1200 思路分析:从数据来看,该题目使用线性时间算法,可见子串的比较是不可能的:使用hash可以在常数时间内查找,可以常数时间内判重, ...

  2. POJ 1200 Crazy Search(字符串简单的hash)

    题目:http://poj.org/problem?id=1200 最近看了一个关于hash的问题,不是很明白,于是乎就找了些关于这方面的题目,这道题是一道简单的hash 字符串题目,就先从他入手吧. ...

  3. POJ – 1200 Crazy Search

    http://poj.org/problem?id=1200 #include<iostream> #include<cstring> using namespace std; ...

  4. POJ 1200 Crazy Search (哈希)

    题目链接 Description Many people like to solve hard puzzles some of which may lead them to madness. One ...

  5. POJ 1200 Crazy Search 【hash】

    <题目链接> 题目大意: 给定n,nc,和一个字符串,该字符串由nc种字符组成,现在要你寻找该字符串中长度为n的子字符串有多少种. 解题分析: 因为要判重,所以讲这些字符串hash一下,将 ...

  6. POJ 1200 Crazy Search【Hash入门】

    RK法:https://www.cnblogs.com/16crow/p/6879988.html #include<cstdio> #include<string> #inc ...

  7. POJ 1200 Crazy Search 字符串的Hash查找

    第一次涉及HASH查找的知识 对于字符串的查找有很多前人开发出来的HASH函数,比较常用的好像是ELF 和 BKDR. 这道题没想到突破点是在于其nc值,告诉你组成字符串的字母种类. 还有用26进制, ...

  8. poj 1200 crasy search

    https://vjudge.net/problem/POJ-1200 题意: 给出一个字符串,给出子串的长度n和给出的字符串中不同字符的个数nc,统计这个字符串一共有多少不同的长度为n的子串. 思路 ...

  9. POJ 1200:Crazy Search(哈希)

    Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32483   Accepted: 8947 Des ...

随机推荐

  1. DataNavigator之分页

    前言 做客户端也有两个月了,先前做列表都没有分页,可能考虑数据也不是很多,昨天做了一个页面,考虑到了数据的问题,所以改为分页查询.因为也是第一次用dev,用哪个控件分页呢,还是要去搜一下,得出的事Da ...

  2. php eval函数用法总结

    可以在php.ini禁止此函数,结果失败了 eval定义和用法  eval() 函数把字符串按照 PHP 代码来计算.  该字符串必须是合法的 PHP 代码,且必须以分号结尾.  如果没有在代码字符串 ...

  3. 关于 hashCode() 你需要了解的 3 件事

    (点击上方公众号,可快速关注) 原文:eclipsesource 译文:ImportNew - 南半球 链接:http://www.importnew.com/16517.html 在 Java 中, ...

  4. Git权威指南 读笔(2)

    第七章 Git重置: Git提供了一个挽救机制,通过.git/logs目录下日志文件记录了分支的变更. master分支的日志文件.git/logs/refs/heads/master,显示最后5行: ...

  5. ionic+angulajs

    基于ionic+angulajs的混合开发实现地铁APP 项目源码地址:https://github.com/zhangxy1035/SubwayMap 一.项目简介 在该项目中的地铁app是基于io ...

  6. iOS 中SQLite数据库操作

    在iOS中实现SQLite数据库的操作:1.导入框架(libsqlite3.0.tbd) 2.导入头文件<sqlite3.h> 3.实现数据的增删改查 实现简单 SQLite数据库操作 的 ...

  7. yum和rpm命令详解

    rpm,全称RPM Package Manager,是RedHat发布的,针对特定硬件,已经编译好的软件包.安装之后就可以使用,不需要自行编译,以及之前对软件和硬件的检测,目录的配置等动作. yum, ...

  8. A Full Hardware Guide to Deep Learning

    A Full Hardware Guide to Deep Learning Deep Learning is very computationally intensive, so you will ...

  9. java多线程下载和断点续传

    java多线程下载和断点续传,示例代码只实现了多线程,断点只做了介绍.但是实际测试结果不是很理想,不知道是哪里出了问题.所以贴上来请高手修正. [Java]代码 import java.io.File ...

  10. HDU3362+状态压缩

    dp[ i ]表示该状态下得所需花费. /* 状态压缩dp dp[i] = min( dp[ i-j ]+cost[ j ] ); 由i-j的状态转到i的状态 */ #include<stdio ...