字符串哈希题目总结
来源:互联网 发布:mysql返回上一级 编辑:程序博客网 时间:2024/05/22 02:35
HDU1880
给出对应的字符串,需要建立相应的双向映射。也就是输入first串可以得出对应的second串,输入second串可以得出对应的first串
数据有100000 ,用map<string,string>模拟爆内存。
使用 BKDRHash 哈希函数进行哈希
// BKDR Hash Functionunsigned 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 <iostream>#include <cstdio>#include <algorithm>#include <cstring>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<H;i++){ hashTableA[i] = -1; hashTableB[i] = -1; } curA = 0; curB = 0;}unsigned int getHash(char *s){ unsigned int seed = 131; unsigned int hash = 0; while(*s){ hash = hash * seed + *s++; } return (hash & 0x7fffffff) % H;}void insertHash(char *que,char *ans){ unsigned int h; h = getHash(que); strcpy(nodeA[curA].que, que); strcpy(nodeA[curA].ans, ans); nodeA[curA].next = hashTableA[h]; hashTableA[h] = curA; ++curA; h = getHash(ans); strcpy(nodeB[curB].que,que); strcpy(nodeB[curB].ans,ans); nodeB[curB].next = hashTableB[h]; hashTableB[h] = curB; ++curB;}int searchHashA(char *que){ unsigned int h = getHash(que); int next = hashTableA[h]; while(next != -1){ if(strcmp(que,nodeA[next].que) == 0) return next; next = nodeA[next].next; } return -1;}int searchHashB(char *ans){ unsigned int h = getHash(ans); int next = hashTableB[h]; while(next != -1){ if(strcmp(ans, nodeB[next].ans) == 0) return next; next = nodeB[next].next; } return -1;}int main(){ char str[120], que[25], ans[85],qlen ,alen; int n,res; initHash(); while(gets(str)){ if(str[0] == '@') break; qlen = 0; for(int i=1;str[i] != ']';++i){ que[qlen++] = str[i]; } que[qlen] = 0; alen = 0; for(int i=qlen+3; str[i] != 0; ++i){ ans[alen++] = str[i]; } ans[alen] = 0; insertHash(que,ans); } scanf("%d",&n); getchar(); while(n--){ gets(str); if(str[0] == '['){ qlen = strlen(str); str[qlen - 1] = 0; res = searchHashA(str + 1); if(res == -1) printf("what?\n"); else printf("%s\n",nodeA[res].ans); }else{ alen = strlen(str); res = searchHashB(str); if(res == -1) printf("what?\n"); else printf("%s\n",nodeB[res].que); } } return 0;}
POJ1743
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。“主题”是整个音符序列的一个子串,它需要满足如下条件:
后缀数组可解,
这里用到88进制取模进行哈希函数
想出这种方法的作者连接 http://blog.renren.com/share/283538506/12293487302/0
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cstdlib>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<n;i++) if(H.insert(S[i] - S[i-x]*P[x],i ) < i - x) return true; return false;}int main(){ P[0] = 1; for(int i=1;i<maxn;i++) P[i] = P[i-1] * SEED; // unsigned long long 自动取模 while(scanf("%d",&n) && n){ for(int i=1;i<=n;i++) scanf("%d",&A[i]); for(int i=1;i<n;i++) A[i] = A[i + 1] - A[i]; S[0] = 0; for(int i=1;i<n;i++) S[i] = S[i-1] * SEED + A[i]; int ans = 0; int l = 4, r = n - 1; while(l <= r){ int mid = (l + r) >>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<cstdio>#include<algorithm>#include<map>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<cstdlib>#include<iostream>using namespace std;#define maxn 5000006typedef unsigned long long ll;ll hash = 100007;ll hash_w;ll hash_p [maxn];ll hash_pow[maxn];char p[maxn], w[maxn];char stack[maxn];int len ;void init(){ hash_pow[0] = 1; for(int i=1;i<maxn;i++) hash_pow[i] = hash_pow[i -1] *hash;}bool check(int pos){ if(pos >= len && hash_p[pos] - hash_p[pos - len] *hash_pow[len] == hash_w ){ // cout<<pos<<" "<<hash_p[pos] <<" "<<hash_p[pos - len] *hash_pow[len]<<endl; return true; } return false;}int main(){ init(); while(~scanf("%s%s",w,p)){ len = strlen(w); //模式串的hash值 hash_w = 0; for(int i=0;*(w + i);i++){ hash_w = hash_w * hash + *(w + i); // cout<<hash_w<<" xx "; } // cout<<endl; int top = 0; for(int i=0; *(p + i); i++){ stack[top++] = *(p + i); hash_p[top] = hash_p[top - 1]*hash + *(p + i); if(check(top)) top -= len; } for(int i=0;i<top;i++) printf("%c",stack[i]); puts(""); } return 0;}
HDU1280整数hash 水题
#include<cstdio>#include<algorithm>#include<map>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<cstdlib>#include<iostream>using namespace std;#define maxn 5000006typedef 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<n;i++){ scanf("%d",&arr[i]); } for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ vis[arr[i] + arr[j] ] ++; } } bool isfirst = true; for(int i=10000;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;}
HDU1496
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<cstdio>#include<algorithm>#include<map>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<cstdlib>#include<iostream>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;}
ACDREAM 1726
给出N个数 和一个数 H ,从N个数中选择任意多个数,问有多少种选择使得选的数的和 等于H 。
N <=40 H <= 1e9
1e9需要哈希一下。
N = 40 折半之后哈希就可以了。
二分数据,数据减半后,时间复杂度 有 2 ^ 40 变为 2 ^ 20;
再用HASH判断是否满足
#include<cstdio>#include<algorithm>#include<map>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<cstdlib>#include<iostream>using namespace std;typedef long long ll;#define mem(a,x) memset(a,x,sizeof a)const int maxn = 1<<20; // 1048576const int hash = 1000007; //开多大的hash/*3 1000010next记录的是之前的headhead代表着数据在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<n;i++) scanf("%d",num+i); int t = n/2; // 将t种取或者不取 映射为二进制数,进行枚举 for(int i=0;i<(1<<t);i++){ ll sum = 0; for(int j=0;j < t;j++){ if(i & (1<<j)){ sum += num[j]; //加上选中的数 } } if(sum > m) continue; h1.add(sum); } int tt = n - t; //枚举剩下的数 int flag = 0; for(int i=0;i<(1<<tt);i++){ ll sum = 0; for(int j=0;j<tt;j++){ if(i & (1<<j)) sum += num[t + j]; //加上剩下的数中符合条件的 } if(sum > m) continue; if(h1.find(m - sum)){ flag = 1; break; } } if(flag) printf("Yes\n"); else printf("No\n"); } return 0;}
- 字符串哈希题目总结
- 字符串题目总结
- ACM字符串题目总结
- leetcode_387(字符串题目总结)
- C语言字符串面试题目总结
- 字符串题目
- 字符串题目
- 常用算法题目总结四(字符串篇)
- 题目总结
- 题目总结
- 字符串模板总结(二):字符串哈希
- 字符串的题目
- 面试题目 字符串专题
- 两个小字符串题目
- HDOJ字符串题目【容易】
- 字符串题目A
- 面试题目 字符串专题
- 题目1490:字符串链接
- [Oracle]linux环境下全库还原Oracle数据库备份
- java 静态变量生命周期(类生命周期)
- docker打包RabbitMq
- C语言中对文件的操作
- JavaScript引 用 类 型【Object,Array】(一)
- 字符串哈希题目总结
- HDU3336Count the string(KMP+动态规划)
- 深入理解Java:类加载机制及反射
- service worker介绍
- 11.剑指offer-从左到右打印二叉树
- 两行代码给你带来漂亮的侧滑栏
- 深拷贝与浅拷贝
- 静态成员函数与非静态成员函数的区别
- 循序渐进学HotFix (基于Gradle 1.5+版本)