poj 1200 --- 不错的字符串HASH构造方法

题目:http://poj.org/problem?id=1200

题意:给一个字符串,给定n和nc,字符串里最多有nc个不同的字符,问长度为n的不同子串最多有几个

和上一篇现场赛那个一样,也是难在判重处理不好会超时

方法:将长度为n的子串映射为一个nc进制的数,开一个大数组,判断是否重复

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <map>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdin)

const int MAXN = 16000000+100;

bool Hash[MAXN];
char str[MAXN];
int m[1001];
int n,nc;
int ah,base;///

int main()
{
    //IN("poj1200.txt");
    int ans,len,seed;
    while(~scanf("%d%d",&n,&nc))
    {
        CL(Hash,0);CL(m,0);
        ah=0;ans=0;seed=0;
        scanf("%s",str);
        len=strlen(str);
        if(len<n){puts("0");continue;}
        rep(i,0,len)
        {
            if(!m[str[i]])m[str[i]]=++seed;
            if(seed == nc)break;
        }
        ah=m[str[0]],base=nc;
        for(int i=1;i<n;i++)
        {
            ah=ah*nc+m[str[i]];
            base*=nc;
        }
        Hash[ah]=1;ans++;
        rep(i,n,len)
        {
            ah=ah*nc-m[str[i-n]]*base+m[str[i]];
            if(!Hash[ah])
            {
                Hash[ah]=1;
                ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

poj 1200 --- 不错的字符串HASH构造方法

时间: 2024-10-08 15:16:39

poj 1200 --- 不错的字符串HASH构造方法的相关文章

POJ 1200 Crazy Search(Hash)

Description Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a given text. Such number could be the number of different substrings of a given size that exist in t

POJ 1200 Crazy Search (字符串hash)

题目大意: 分析长度为n的子串有多少种. 思路分析: 对于没出现的字符,将其分配一个数字. 然后将子串看做一个nc进制的数. 然后hash判断. #include <cstdio> #include <iostream> #include <algorithm> #include <map> #include <cstring> #include <string> using namespace std; bool vis[26666

POJ 1200 字符串HASH

题目链接:http://poj.org/problem?id=1200 题意:给定一个字符串,字符串只有NC个不同的字符,问这个字符串所有长度为N的子串有多少个不相同. 思路:字符串HASH,因为只有NC个不同的字符,所以我们可以把字符串看成是一个NC进制的串,然后计算出字符串的前缀HASH.然后枚举起点判断子串的HASH值是否已经存在.因为有了前缀HASH值,所以转移是O(1)的. #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #in

Poj 1200 Crazy Search(字符串Hash)

Poj 1200 题意:给你一个n和m以及一个有m个不同字母组成的字符串,问有多少个长度为n的不同字符子串: 题解:以m为进制进行Hash.虽然是看了解题报告才会的但必须要理解并且学会运用:https://www.cnblogs.com/gj-Acit/archive/2013/05/15/3080734.html. #include<cstring>//别用set,set的添加是红黑树实现时间复杂度是O(logN),在这里会超时 #include<cstdio> #define

字符串hash - 简单的字符匹配 --- poj 3461

Oulipo Problem's Link:http://poj.org/problem?id=3461 Mean: 给你一个模式串P和一个母串S,让你统计P串在S串中出现的次数. analyse: 这题我一开始想到的就是使用KMP,就用KMP写了,93ms,挺快的.我又用AC自动机写了一遍(纯属娱乐),万万没想到竟然超时了,是我姿势不对么? 后来看别人有用字符串hash写的,听说字符串hash在某些问题中比AC自动机什么的厉害多了,于是又用字符串hash写了一遍,确实挺不错的,代码30+行,而

【POJ 1200】Crazy Search(将字符映射为数字,将NC进制hash成10进制)

题目链接 题目链接 http://poj.org/problem?id=1200 题意 原字符串有NC个不同字母,统计原字符串长度为N的子字符串个数 解题思路 将字符按ASCII码映射成数字. 将n个字符,即n位NC进制拼起来. 将拼起来的n位NC进制转化为10进制. 将10进制映射入hash表,每次映射判断是否已经存在. 若不存在,则ans++:否则将hash设置为存在 如何将子串(n位NC进制)映射为10进制 a = 0 b = 1 c = 2 则 cbaa = 2 * 3^3 + 1 *

字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍. 这题的思路是这样的: 1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界:不存在就缩小上界): 2)主要是对答案的判断(judge函数

poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机

http://poj.org/problem?id=2774 想用后缀数组的看这里:http://blog.csdn.net/u011026968/article/details/22801015 本文主要讲下怎么hash去找 开始的时候写的是O(n^2 logn)算法 果断超时...虽然也用了二分的,, 代码如下: //hash+二分 #include <cstdio> #include <cstring> #include <algorithm> #include

poj 3461 字符串单串匹配--KMP或者字符串HASH

http://poj.org/problem?id=3461 先来一发KMP算法: #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <cmath> #include <map> #include <queue> using namespace std;