正题
题目大意
一个句子有多个单词。
给出了一个加密了的串。加密方法是将不同的单词转换成不同的单词。然后再给一个加密前的串,求再加密串中可能出现的最早位置。
解题思路
设aia_iai表示与iii相同的前一个字母的位置。
然后根据题目意思对与两个串如果aaa序列一样那么就是可以转换的加密串。所以我们可以用字符串hashhashhash进行匹配。
codecodecode
#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();
}