HDU1880
给出对应的字符串,需要建立相应的双向映射。也就是输入first串可以得出对应的second串,输入second串可以得出对应的first串
数据有100000 ,用map
使用 BKDRHash 哈希函数进行哈希
// BKDR Hash Function
unsigned int BKDRHash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
代码
#include
#include
#include
#include
using namespace std;
const int N = 100010;
const int H = 100007;
struct node{
char que[25];
char ans[85];
int next;
};
node nodeA[N], nodeB[N];
int curA,curB;
int hashTableA[N] , hashTableB[N];
void initHash(){
for(int i=0;i
POJ1743
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:
1.长度至少为5个音符。
2.在乐曲中重复出现。(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值)
3.重复出现的同一主题不能有公共部分。
重复2次以上,不能有公共部分的最长子串。后缀数组可解,
这里用到88进制取模进行哈希函数
想出这种方法的作者连接 http://blog.renren.com/share/283538506/12293487302/0
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxh = 10007;
const int maxn = 20010;
typedef long long ll;
typedef unsigned long long ull;
#define mem(a,x) memset(a,x,sizeof a)
struct HASHMAP{
int head[maxh] , next[maxn] , size;
ull state[maxn];
int f[maxn];
void init(){
size = 0;
mem(head,-1);
}
int insert(ull val,int id){
int h = val % maxh;
for(int i=head[h]; i != -1; i = next[i]){
if(val == state[i]) return f[i];
}
f[size] = id;
state[size] = val;
next[size] = head[h];
head[h] = size++;
return f[size - 1];
}
};
HASHMAP H;
const int SEED = 13331;
ull P[maxn];
ull S[maxn];
int A[maxn];
int n;
bool check(int x){
H.init();
for(int i=x;i>1;
if(check(mid)){
ans = mid;
l = mid +1;
}else
r = mid -1;
}
if(ans < 4) ans = -1;
ans++;
printf("%d\n",ans);
}
return 0;
}
SCU4438 字符串hash ,好题
通过构造hash表,记录模式串的hash值,然后对主串按顺序遍历每个字符,并存入数组stack,并算出当前串的hash值,通过hash[i] - hash[i - len]*hashpow 算出当前子串是否与模式串hash值相等,相等就将数组stack中的下标回退len长度,实现删除匹配的串。
细节还有待推敲
代码
#include
#include
#include
HDU1280整数hash 水题
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 5000006
typedef unsigned long long ll;
#define mem(a,x) memset(a,x,sizeof a)
int arr[3333];
int vis[10010];
int main(){
int n,m;
while(scanf("%d%d",&n,&m) != EOF){
mem(vis,0);
for(int i=0;i=0;i--){
if(!m)break;
while(m && vis[i]){
if(isfirst)
printf("%d",i);
else
printf(" %d",i);
isfirst = false;
m--;
vis[i]--;
}
}
puts("");
}
return 0;
}
a*x1^2+b*x2^2+c*x3^2+d*x4^2=0
给出这样一个式子,给出a,b,c,d.求有多少解, abcd范围 [-50,50] x1 - x4 [-100,100];
hash,四层循环改成二层循环,通过数组映射判断是否冲突,冲突就说明匹配,说明有解。另外特殊情况该优化的还要优化,否者会超时。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef unsigned long long ll;
#define mem(a,x) memset(a,x,sizeof a)
//-50*(10000) *2 = 1e 6;
const int maxn = 1e6 + 2;
int vis[2000010]; //2e6 + 10;
int main(){
int a,b,c,d;
while(scanf("%d%d%d%d", &a,&b,&c,&d) != EOF){
if(a > 0 && b> 0 && c > 0 && d > 0){//没有这句就超市了
puts("0");
continue;
}
mem(vis,0);
for(int i=1;i<=100;i++){
for(int j=1;j<=100;j++){
vis[a*i*i + b*j*j + maxn ] ++;
}
}
int ans = 0;
for(int i=1;i<=100;i++){
for(int j=1;j<=100;j++){
ans += vis[-(c*i*i + d*j*j)+maxn];
}
}
// 每个i ,j都是可正 可负,2 * 2 * 2 * 2 == 16
printf("%d\n",ans*16);
}
return 0;
}
给出N个数 和一个数 H ,从N个数中选择任意多个数,问有多少种选择使得选的数的和 等于H 。
N <=40 H <= 1e9
1e9需要哈希一下。
N = 40 折半之后哈希就可以了。
二分数据,数据减半后,时间复杂度 有 2 ^ 40 变为 2 ^ 20;
再用HASH判断是否满足
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define mem(a,x) memset(a,x,sizeof a)
const int maxn = 1<<20; // 1048576
const int hash = 1000007; //开多大的hash
/*
3 1000010
next记录的是之前的head
head代表着数据在a数组中的位置。
head始终代表着头结点
*/
struct hashmap{
ll a[maxn]; //映射入的数组
int head[hash] , next[maxn],size;
void init(){
mem(head,-1);
size = 0;
}
/*
取模相同的数,存入a中之后,可以通过next遍历找到head进而找到对应a[i];
实现了取模相同的数放到邻接表里一样的查询。
*/
bool find(ll val){ //查找一个元素是否在hash表中
int tmp = (val % hash + hash) % hash;
for(int i=head[tmp]; i != -1;i = next[i]){
if(val == a[i]) return true;
}
return false;
}
void add(ll val){ // 添加元素到hash表
int tmp = (val % hash + hash) %hash;
if(find(val)) return ;
a[size] = val;
next[size] = head[tmp];
head[tmp] = size ++;
}
}h1;
int n,m,num[55];
int main(){
//
// h1.init();
// h1.add(3);
// h1.add(4);
// h1.add(5);
// h1.add(6);
// h1.add(1000010);
// h1.add(2000017);
while(~scanf("%d%d",&n,&m)){
h1.init();
for(int i=0;i m) continue;
h1.add(sum);
}
int tt = n - t; //枚举剩下的数
int flag = 0;
for(int i=0;i<(1< m) continue;
if(h1.find(m - sum)){
flag = 1; break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}