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>
#include<cstring>
#include<string>
#include<cstdio>
#include<set>
using namespace std;
typedef long long int LL;
typedef unsigned int uint;
const int MAXN=16000000+5;
const int mod=16000000+5;
int Hash[MAXN],vis[256];
char str[MAXN];
bool cnt[MAXN];
int pow_mod(int a,int b){
    int ans=1;
    while (b)
    {
          if (b & 1)
              ans = (1LL*ans*a)%mod;
          b >>= 1 ;
          a = (1LL*a*a)%mod;
    }
    return ans;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        int hashNum=0,ans=0;
        scanf("%s",str+1);
        memset(vis,-1,sizeof(vis));
        memset(cnt,false,sizeof(cnt));
        int len=strlen(str+1);
        for(int i=1;i<=len;i++){
            if(vis[str[i]]==-1){
                vis[str[i]]=hashNum;
                Hash[i]=hashNum++;
            }
            else{
                Hash[i]=vis[str[i]];
            }
        }
        int P=pow_mod(m,n-1),pNum=0;
        for(int i=1;i<=len;i++){
            if(i>=n){
                pNum=(((pNum-Hash[i-n]*P)*m+Hash[i])%mod+mod)%mod;
                if(!cnt[pNum]){
                    cnt[pNum]=true;
                    ans++;
                }
            }
            else{
                pNum=(pNum*m+Hash[i])%mod;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-08 15:16:31

POJ 1200 字符串HASH的相关文章

Power Strings POJ - 2406,字符串hash

题目链接:POJ - 2406 题目描述 定义两个字符串s1和s2的乘积s1*s2为将s1和s2连结起来得到的字符串. 例如:s1="xy",s2="z",那么s1*s2="xyz". 由此可以定义s1的幂次:s1^0="",s1^n=s1*s1^(n-1),n>0. 输入 输入包含多组测试数据. 每组数据由一行构成,包含一个字符串s. 输入数据以"."结束. 输出 对于每组输入数据输出一行,找出最大

poj 1200 (hash)

Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23168   Accepted: 6513 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 gi

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 题意:给一个字符串,给定n和nc,字符串里最多有nc个不同的字符,问长度为n的不同子串最多有几个 和上一篇现场赛那个一样,也是难在判重处理不好会超时 方法:将长度为n的子串映射为一个nc进制的数,开一个大数组,判断是否重复 #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include

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 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 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 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;