其他分享
首页 > 其他分享> > 【哈希】POJ 1200 Crazy Search

【哈希】POJ 1200 Crazy Search

作者:互联网

 POJ 1200 Crazy Search

FEELING:乍一看确实是哈希的嘛,一遍扫过去,哈希值有多少个就是多少个不同子串咯。首先就是直接用的字符串匹配的karp-rabin算法(自己定义的base,所以没有用到nc)。emmmMLE了,www. 后来看了这道题的discuss,上面说好好看题,就是用到了nc咯,于是又改成nc进制。还是不对啊WA了。后来就是搜题解,全部都是没有用区间求哈希值,也就是没有预处理。就是遍历的时候才算哈希值。然后开了一个vis数组。这时候问题就来了。这个vis数组开多大?为什么开了16e6就可?后来问了人吧,他的一句话点醒了我,因为我们是将字符串看成nc进制的“大数”,于是我们的子串个数就是大数范围有多大。比如说211,那么211的子串就有211个。反正我现在还是觉得这个题很诡异。搞不懂,想不明白。www

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 16000000 + 7;
const int base = 27;
int n, nc;
char s[maxN];
int disc[26];
bool vis[maxN];
void init()
{
    memset(disc, 0, sizeof(disc));
    memset(vis, false, sizeof(vis));
}
int main()
{
    while(~scanf("%d%d", &n, &nc))
    {
        init();
        getchar();
        scanf("%s", s);
        int len = strlen(s);
        int tot = 1;
        for(int i = 0; i < len; i ++ )
        {
            if(!disc[s[i] - 'a'])
                disc[s[i] - 'a'] = tot ++;
            if(tot > nc) break;
        }
        int ans = 0;
        for(int i = 0; i <= len - n; i ++ )//枚举长度为n的字符串的开头
        {
            int Hash = 0;
            for(int j = i; j < i + n; j ++ )
                Hash = Hash * tot + disc[s[j] - 'a'];
            if(!vis[Hash])
            {
                vis[Hash] = true;
                ans ++;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

Eve_Miracle* 发布了191 篇原创文章 · 获赞 57 · 访问量 1万+ 私信 关注

标签:子串,Crazy,进制,int,nc,1200,POJ,哈希,include
来源: https://blog.csdn.net/weixin_44049850/article/details/104079945