分析:第一次寫字符串hash,學習的AC代碼的寫法。
其實就是把字符串變成一個p1進制的數(Mod1),由於有衝突:所以用兩種方法表示:p2進制的數。
此題需要注意的點:原串中掃一遍去掉一個點時,如果相鄰的兩個點一樣,那麼去掉以後效果是一樣的,這種情況只要算一遍。
代碼:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
const int maxn = 100010;
const int p1= 17,p2 = 19,Mod1 = 1e9+7,Mod2 = 1e9+9;
map <PII,int> hs;
LL h1[maxn],h2[maxn],f1[maxn],f2[maxn];
char str[maxn];
int n,m;
PII geths(int l,int r){
if(l == 0) return mp(f1[r],f2[r]);
if(l > r) return mp(0,0);
return mp((f1[r]-f1[l-1]*h1[r-l+1]%Mod1+Mod1)%Mod1,
(f2[r]-f2[l-1]*h2[r-l+1]%Mod2+Mod2)%Mod2);
}
int main(){
//freopen("in.txt","r",stdin);
h1[0] = h2[0] = 1;
FOR(i,1,maxn) h1[i] = h1[i-1]*p1%Mod1,h2[i] = h2[i-1]*p2%Mod2;
sc2(n,m);
FOR(i,0,n){
scanf("%s",str);
int len = strlen(str);
f1[0] = f2[0] = str[0]-'a';
FOR(j,1,len){
f1[j] = (f1[j-1]*p1%Mod1+str[j]-'a')%Mod1;
f2[j] = (f2[j-1]*p2%Mod2+str[j]-'a')%Mod2;
}
hs[mp((f1[len-1]-h1[len-1]*f1[0]%Mod1+Mod1)%Mod1,
(f2[len-1]-h2[len-1]*f2[0]%Mod2+Mod2)%Mod2)] ++;
FOR(j,1,len){
if(str[j] == str[j-1]) continue;
PII x = geths(0,j-1),y = geths(j+1,len-1);
hs[mp((x.fi*h1[len-1-j]%Mod1+y.fi)%Mod1,
(x.se*h2[len-1-j]%Mod2+y.se)%Mod2)] ++;
}
}
FOR(i,0,m){
scanf("%s",str);
int len = strlen(str);
LL sum1,sum2;
sum1 = sum2 = str[0]-'a';
FOR(j,1,len){
sum1 = (sum1*p1%Mod1+str[j]-'a')%Mod1;
sum2 = (sum2*p2%Mod2+str[j]-'a')%Mod2;
}
printf("%d\n",hs[mp(sum1,sum2)]);
}
return 0;
}