zoukankan      html  css  js  c++  java
  • 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 ull unsigned long long
    using namespace std;
    const int N=1e7+6e6+5;
    using namespace std;
    int p[N];
    int len;
    char str[N];
    bool hash_[N];
    int main(){
        int n,m;
        scanf("%d %d %s",&n,&m,str+1);
        len=strlen(str+1);
        int j=0;
        for(int i=1;i<=len;i++){
            if(!p[str[i]])p[str[i]]=++j;//以m为进制数,将各个字母分别用数字表示进行hash
            if(j==m)break;
        }
        ull Base=1;
        ull Hash=0;
        for(int i=1;i<=n;i++){//首先将前n个数将m进制转换为10进制
            Hash=Hash*m+p[str[i]]-1;//减一是为了因为m进制数为0到m-1
            Base*=m;
        }
        Base/=m;
        hash_[Hash]=1;
        int ans=1;
        for(int i=2;i+n<=len+1;i++){
            Hash=(Hash-(p[str[i-1]]-1)*Base)*m+p[str[i+n-1]]-1;//原Hash减去子串首字母代表的数乘以Base得到的是剩下字母所生成的10进制数那么再乘以一个m在加上新进的一个字母所代表的数,得到的是新子串所代表的10进制数(即其hash值)
            if(!hash_[Hash]){
                hash_[Hash]=1;
                ans++;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    栈及练习
    约瑟夫问题
    双向链表
    链表
    线性表
    高级排序
    建议16:比较函数调用模式
    建议15:推荐动态调用函数
    建议14:灵活使用Arguments
    建议13:禁用Function构造函数
  • 原文地址:https://www.cnblogs.com/Mrleon/p/8424434.html
Copyright © 2011-2022 走看看