我的第一题字符串哈希。
ac代码
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define ll long long
#define maxn 16000005
int n,base;
int ss[maxn];
int vis[500];
char s[maxn];
int main()
{
scanf("%d %d %s",&n,&base,s+1);
memset(vis,-1,sizeof(vis));
int len=strlen(s+1);
int cnt=0;
ll ans=0;
for(int i=1;i<=len;i++)
{
if(vis[s[i]]==-1)
{
vis[s[i]]=cnt++;
}
ss[i]= vis[s[i]];
}
//cout<<cnt<<endl;
long long hsh=0;
if(len<n)
printf("%lld
",ans);
else
{
ll qz=1;
for(int i=1;i<=n;i++)
{
hsh=(ll)(hsh*base+ss[i]);
if(i<=n-1)
qz*=base;
}
s[hsh]='*';//把字符串s转化为整数序列后,s就没有用了,我索性拿来做标记,标记哪些子串统计过了
ans++;
for(int i=n+1;i<=len;i++)
{
hsh-=ss[i-n]*qz;
hsh*=base;
hsh+=ss[i];
if(s[hsh]!='*')
{
s[hsh]='*';
ans++;
}
}
printf("%lld
",ans);
}
return 0;
}
贴一个我的另外一个代码,用的另一种方法但是一直wa,至今没找到bug
#include<stdio.h>
#include<iostream>
#include<map>
#include<string.h>
using namespace std;
#define ll long long
const int maxn=16000005;
map<ll,ll>mp;
ll ihash[maxn]={0};
char s[maxn];
const ll mod1=1e9+7;
const ll base=79;
long long k=1;
int n,nc;
int main()
{
mp.clear();
scanf("%d %d %s",&n,&nc,s+1);
int len=strlen(s+1);
ll ans=0;
for(int i=1;i<=len;i++)
{
ihash[i]=(ihash[i-1]*base+(ll)s[i])%mod1;
if(i<=n)
k=k*base;
}
// cout<<endl;
// for(int i=1;i<=len;i++)
// cout<<ihash[i]<<" ";
// cout<<endl;
for(int low=1;low<=len+1-n;low++)
{
int up=low+n-1;
ll tmp=ihash[up]-ihash[low-1]*k;
if(tmp<0)
tmp+=mod1;
//cout<<"tmp:"<<tmp<<endl;
if(mp[tmp]==0)
{
mp[tmp]=1;
ans++;
}
}
printf("%lld
",ans);
return 0;