# 字符串匹配(hash算法）

hash函数对大家来说不陌生吧 ？

hash用的也是一样的原理，为每一个前缀（也可以后缀，笔者习惯1 base，所以喜欢用前缀来计算，Hash[i] = Hash[i - 1] * x + s[i](其中1 < i <= n,Hash[0] = 0)。

typedef unsigned long long ull;
const int N = 100000 + 5;
const ull base = 163;
char s[N];
ull hash[N];

void init(){//处理hash值
p[0] = 1;
hash[0] = 0;
int n = strlen(s + 1);
for(int i = 1; i <=100000; i ++)p[i] =p[i-1] * base;
for(int i = 1; i <= n; i ++)hash[i] = hash[i - 1] * base + (s[i] - 'a');
}

ull get(int l, int r, ull g[]){//取出g里l - r里面的字符串的hash值
return g[r] - g[l - 1] * p[r - l + 1];
}


hash水题（附AC代码）：

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
const int N = 100000 + 5;
const ull base = 163;
ull Hash1[N], Hash2[N], p[N];

char s[N], t[30], r[N];

int T;

int c[30];

void init(){
p[0] = 1;
for(int i = 1; i <=100000; i ++)p[i] =p[i-1] * base;
}

ull get(int l, int r, ull g[]){
return g[r] - g[l - 1]*p[r - l + 1];
}

void work(){
for(int i = 0; i < 26; i ++) c[t[i] - 'a'] = i;
//puts(r+1);
int n = strlen(s + 1);
Hash1[0] = Hash2[0] = 0;
for(int i = 1; i <= n; i ++){
Hash1[i] = Hash1[i - 1] * base + (s[i] - 'a');
Hash2[i] = Hash2[i - 1] * base + (c[s[i] - 'a']);
}
int ans = n;
for(int i = n; i < n * 2; i ++){
if(i & 1) continue;
int tmp = i / 2;
int len =n - tmp;
ull s1 = get(1, len, Hash2);
ull s2 = get(n - len + 1, n, Hash1);
if(s1 == s2){
ans = tmp;
break;
}
//printf("%llu %llu\n", s1, s2);
}
//printf("ans = %d\n", ans);
for(int i = 1; i <= ans; i ++)printf("%c", s[i]);
for(int i = 1; i <= ans; i ++)printf("%c", c[s[i]-'a'] + 'a');
puts("");
}

int main(){
scanf("%d", &T);
init();
while(T--){
scanf("%s%s", t, s + 1);
work();
}
return 0;
}


posted @ 2015-09-14 13:41  殇雪  阅读(23224)  评论(14编辑  收藏  举报