版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/89001725
手打一个代码比较相似度的程序
给定两个串,现在假设某个串会代替某个串,求从哪个位置开始正好匹配成功
数据范围:
字符串模式匹配
但是我们不能直接 ,因为我们不知道每个字符串到底代表这什么
但是我们可以求出之前与它相同的串的间隔距离(用 求),以此分别作为 和 ,再进行 即可
不过要特判可以直接对上的情况
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#define LL long long
#define WYC 200560490131ll
#define ZYC 999983
#define N 1000010
using namespace std;
LL e[N],h[N*2],cx[N],t;
int a[N],b[N],next[N],pre,n,m,j;
char s[N];
inline int hash(LL x,int n)
{
LL y=x%ZYC;
while(h[y])
{
if(h[y]==x)
{
int t=cx[y];//取出之前出现的位置
cx[y]=n;//放入现在的位置
return t;
}
y=(y+1)%2000000;
}
h[y]=x;cx[y]=n;
return 0;
}
signed main()
{
e[0]=1;
for(register int i=1;i<=1000000;i++) e[i]=e[i-1]*27%WYC;
while(scanf("%s",s+1),s[1]!='$')
{
n++;
t=0;
for(register int i=1;i<=strlen(s+1);i++) t=(t+(s[i]-96)*e[i-1]%WYC)%WYC;
pre=hash(t,n);
if(!pre) a[n]=pre;else a[n]=n-pre;
}
scanf("\n");
memset(h,0,sizeof(h));memset(cx,0,sizeof(cx));
while(scanf("%s",s+1),s[1]!='$')
{
m++;
t=0;
for(register int i=1;i<=strlen(s+1);i++) t=(t+(s[i]-96)*e[i-1]%WYC)%WYC;
pre=hash(t,m);
if(!pre) b[m]=pre;else b[m]=m-pre;
}
j=0;
for(register int i=2;i<=m;i++)
{
while(j&&b[j+1]!=b[i]) j=next[j];
if(b[j+1]==b[i]) j++;
next[i]=j;
}
j=0;
for(register int i=1;i<=n;i++)
{
while(j&&!(b[j+1]==a[i]||(b[j+1]==0&&a[i]>j))) j=next[j];
if(b[j+1]==a[i]||(b[j+1]==0&&a[i]>j)) j++;//后面那个括号是特判
if(j==m) return printf("%d\n",i-m+1)&0;
}
}