P3370字符串哈希
进制哈希:
给出一个固定进制base,将一个串的每一个元素看作一个进制位上的数字,所以这个串就可以看作一个base进制的数
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef unsigned long long ull;
ull base=131;
ull a[10010];
char s[10010];
int n,ans=1;
int prime=233317;
ull mod=212370440130137957ll;
ull hashe(char s[])
{
int len=strlen(s);
ull ans=0;
for (int i=0;i<len;i++)
ans=(ans*base+(ull)s[i])%mod+prime;
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
a[i]=hashe(s);
}
sort(a+1,a+n+1);
for(int i=1;i<n;i++)
{
if(a[i]!=a[i+1])
ans++;
}
printf("%d",ans);
}
主要思想就是设置一个函数,通常使用取模换进制等,两次扫描,排序,比较a[i]
双hash思想
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull base=131;
struct data
{
ull x,y;
}a[10010];
char s[10010];
int n,ans=1;
ull mod1=19260817;
ull mod2=19660813;
ull hash1(char s[])
{
int len=strlen(s);
ull ans=0;
for (int i=0;i<len;i++)
ans=(ans*base+(ull)s[i])%mod1;
return ans;
}
ull hash2(char s[])
{
int len=strlen(s);
ull ans=0;
for (int i=0;i<len;i++)
ans=(ans*base+(ull)s[i])%mod2;
return ans;
}
bool comp(data a,data b)
{
return a.x<b.x;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",s);
a[i].x=hash1(s);
a[i].y=hash2(s);
}
sort(a+1,a+n+1,comp);
for (int i=2;i<=n;i++)
if (a[i].x!=a[i-1].x || a[i-1].y!=a[i].y)
ans++;
printf("%d\n",ans);
}
就是说不用哈希的话链表的stl自带unique
#include<bits/stdc++.h>
using namespace std;
list<string>q;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
string s;
cin>>s;
q.push_front(s);//加入链表
}
q.sort();//排序
q.unique();//去重
cout<<q.size();
}
或者可以立flag
一开始全是零,然后每一个都向后遍历,有相同的设为1
#include<bits/stdc++.h>
using namespace std;
string s[10000000];
bool flag[1000000];
long long ans;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
for(int i=1;i<=n;i++)
{
if(flag[i]==1)
{
ans++;
continue;
}
for(int j=i+1;j<=n;j++)
{
if(s[j]==s[i])
{
flag[j]=1;
flag[i]=1;
}
}
}
cout<<n-ans;
}