Poj Crazy Search

这个题数据又小又水。一个点N=5,M=24,另一个点N=7,M=8。字符串长度<=1000000,随便乱做都可以过。

/*
Sol:由于本题已告诉大家,子串个数<=1000000,
所以我们只需要将字符串hash成一个数字
将它们放到一个数组中,接下来是去重的工作,
于是可以快排,这样数字就有序了。
接下来可以进行去重工作
*/ 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define P 29
#define maxn 1000010
using namespace std;
unsigned long long  n,c,len,p[maxn],ha[maxn],tot,hashh[maxn],ans;
char s[maxn];

void Get_p()
{
    p[0]=1;
    for(int i=1;i<=n;i++)
        p[i]=p[i-1]*P;
}

void Get_ha()
{
    len=strlen(s+1);
    for(int i=1;i<=len;i++)
      ha[i]=ha[i-1]*P+s[i]-'a';
}

unsigned Query(int l,int r)
{
    return ha[r]-ha[l-1]*p[r-l+1];
}

void Solve()
{
    for(int l=1;l+n-1<=len;l++)
    {
        int r=l+n-1;
        hashh[++tot]=Query(l,r);
    }
    sort(hashh+1,hashh+1+tot);
    for(int i=1;i<=tot;i++)
      if(hashh[i]!=hashh[i-1])ans++;
}

int main()
{
	
    scanf("%d%d%s",&n,&c,s+1);
    Get_p();Get_ha();Solve();
    printf("%d
",ans);
    return 0;
}


/*
解析:由于取出来的子串长度<=7,字符的种类<=24,也就意识着
我们将字符串hash出来的数值不会太大,是<=24^7,于是可以
直接开一个bool数组来进行去重工作 
*/
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
using namespace std;
int n,nc,num=0,ans=0; 
string s;
bool Vis[1005];
int V[1005];
bool Hash[16000005];
int main()
{
	cin>>n>>nc;
	cin>>s;
	int len=s.length();
	for(int i=0;i<len;++i) 
	{
		if(!Vis[s[i]])
		{
			Vis[s[i]]=true;
			V[s[i]]=++num;
		}
	}
	for(int i=0;i<=len-n;++i)
	{
		int sum=0; 
		for(int j=i;j<i+n;++j)
		{
			sum+=nc*sum+V[s[j]];
		} 
		if(!Hash[sum])
		{
			ans++;
			Hash[sum]=true;
		}
	}
	cout<<ans<<endl;
	return 0;
}

  如果hash出来的数字很大,则只能用hash,或用set,或map进行查重了(用这两个就是好写点,但多了个Log)

上题也可以这样做,但明显速度慢了许多。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
map<char,int>q;
map<ull,int>p;
int n,m,len,noww=0,ans=0;
char s[20000000];
ull power[1000000],sum[1000000];
int get(int l,int r)
{
	return sum[r]-sum[l-1]*power[r-l+1];
}
int main()
{
	scanf("%d%d%s",&n,&m,s+1);
	len=strlen(s+1);
	power[0]=1;
	for(int i=1;i<=len;i++)
	{
		power[i]=power[i-1]*m;
		if(q[s[i]]==0)q[s[i]]=++noww;
	}
	for(int i=1;i<=len;i++)
	     sum[i]=sum[i-1]*m+q[s[i]];
	for(int i=1;i<=len-n+1;i++)
	{
		ull a=get(i,i+n-1);
		if(p[a]==0)p[a]=1,ans++;
	}
	printf("%d
",ans);

	return 0;
}

  对于一些精心构造过的数据,则可用双hash

https://www.cnblogs.com/cutemush/p/12374102.html

原文地址:https://www.cnblogs.com/cutemush/p/12391056.html