正题
题目大意
一个句子有多个单词。
给出了一个加密了的串。加密方法是将不同的单词转换成不同的单词。然后再给一个加密前的串,求再加密串中可能出现的最早位置。
解题思路
设
a
i
a_i
ai表示与
i
i
i相同的前一个字母的位置。
然后根据题目意思对与两个串如果
a
a
a序列一样那么就是可以转换的加密串。所以我们可以用字符串
h
a
s
h
hash
hash进行匹配。
c o d e code code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const ll XJQ=1000000007;
const ll HZB=10007;
const ll p1=9999991;
const ll p2=1000007;
const ll N=1000001;
ll hash1[N],hash2[N],a[N],b[N];
ll len1,len,s,ans;
char c[N];
map<ll,ll> f;
void pre_work(){
hash1[0]=hash2[0]=1;
for(ll i=1;i<N;i++){
hash1[i]=hash1[i-1]*p1%XJQ;
hash2[i]=hash2[i-1]*p2%XJQ;
}
}
ll work_in(){
ll len,s=0,s1=0;
len=strlen(c);
for(ll i=0;i<len;i++)
{
s=(s*26+c[i]-'a')%XJQ;
s1=(s1*26+c[i]-'a')%HZB;
}
return s+s1*XJQ;
}
void init(){
scanf(" %s",c);
while(c[0]!='$'){
ll x=work_in();
a[++len1]=f[x];
b[a[len1]]=len1;
f[x]=len1;
scanf(" %s",c);
}
scanf(" %s",c);
f.clear();
while(c[0]!='$'){
ll x=work_in();
ll z=f[x];
++len;
s=(s*p2)%XJQ;
if(z)
(s+=hash1[len-z])%=XJQ;
f[x]=len;
scanf(" %s",c);
}
}
void work(){
for(ll i=1;i<=len;i++){
ans=(ans*p2)%XJQ;
if(a[i])
(ans+=hash1[i-a[i]])%=XJQ;
}
if(ans==s){
printf("1");
return;
}
ll l=0;
for(ll i=len+1;i<=len1;i++){
l++;
if(b[l]&&b[l]<i)
(ans-=hash1[b[l]-l]*hash2[i-b[l]-1]%XJQ-XJQ)%=XJQ;
ans=(ans*p2)%XJQ;
if(a[i]&&a[i]>l)
(ans+=hash1[i-a[i]])%=XJQ;
if(l==29767)
l++,l--;
if(ans==s){
printf("%lld",l+1);
return;
}
}
printf("0");
}
int main()
{
freopen("data.in","r",stdin);
pre_work();
init();
work();
}