POJ 1200

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

本题涉及到了一些基本的哈希。。。。

哈希的思路就是把字符转化成可以相加减的具体数字,举个例子。。。

判断字符串 "123132" 和 字符串 "213233"是否相等,是很容易做到的。。我们把他们当做数字来看,只需要看看这两个数字,a1是否等于 a2 就可以了,哈希的思路和这个也很相似

首先 我们把这m 个字符重新赋值一下,

char s[maxn];
ll num[maxn]; 
int zz = 0;
num[s[0]] = zz++;
memset(num,0,sizeof(num));
for(int i=1;i<len;i++)
{
     if(num[s[i]] == 0)
          num[s[i]] = zz ++;
}

重新复制之后,我们再把连续的字符串 变成一个连续 m 进制的数字(因为会有m个不同字符)

  for(int i=0;i<=len-n;i++)
  {
      int sum = 0;
      for(int j=0;j<n;j++)
          sum = sum * zz + num[s[i + j]]; // 对某一串长度为n具体字符串赋值
  }

有了 sum,我们只需判断 sum 是否出现过,就可以了。。。。

 

 

以下是 AC 代码

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long int
const int maxn = 16000003;
char s[maxn];
int has[maxn];
int num[300];
int n,m;
void init(char *s)
{
    int len = strlen(s);
    int zz = 0;
    num[s[0]] = zz++;
    for(int i=1;i<len;i++)
    {
        if(num[s[i]] == 0)
            num[s[i]] = zz ++;
    }
}
int gethas(int l,int r)
{
    int sum = 0;
    for(int i=l;i<=r;i++)
    {
        sum = sum * m + num[s[i]];
    }
    return sum;
}
int main()
{
    while(~scanf("%d%d%s",&n,&m,s))
    {
        int ans = 0;
        int len = strlen(s);
        init(s);
        for(int i=0;i<=len-n;i++)
        {
            int cnt = gethas(i, i+n-1);
            if(!has[cnt])
            {
                ans ++;
                has[cnt] = 1;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值