转自http://blog.csdn.net/w20810/article/details/48438047
题意:给定字符串A和B,在A里面找一个子串s,在s里面最多修改2个字符后使得s和B相同。求s的起始位置。
还是那种套路,不过这个地方的f1,f2,f3表示得挺好的。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 2e5+6;
const int seed = 131;
ULL H[maxn],X[maxn];
char s1[maxn],s2[maxn];
int Len1,Len2,L;
void Init()
{
H[L]=0;
for(int i=L-1;i>=0;i--)
H[i]=H[i+1]*seed+s1[i]-'a';
X[0]=1;
for(int i=1;i<L;i++)
X[i]=X[i-1]*seed;
}
inline ULL GetHash(int i,int L) //
{
return H[i]-H[i+L]*X[L];
}
int LCP(int a,int b)
{
int ret=0,down=1,up=L-b,mid;
while(down<=up)
{
mid=(down+up)>>1;
if(GetHash(a,mid)==GetHash(b,mid))
{
down=mid+1;
if(mid>ret)
ret=mid;
}
else
up=mid-1;
}
return ret;
}
int main()
{
int ncase,i,j,f1,f2,f3,ans;
scanf("%d",&ncase);
for(int T=1;T<=ncase;T++)
{
scanf("%s%s",s1,s2);
Len1=strlen(s1);
Len2=strlen(s2);
L=Len1+Len2;
strcat(s1,s2);
Init();
for(i=0;i<=Len1-Len2;i++)
{
f1=LCP(i,Len1);
if(f1==Len2)
break;
f1++;
f2=LCP(i+f1,Len1+f1);
if(f1+f2==Len2)
break;
f2++;
f3=LCP(i+f1+f2,Len1+f1+f2);
if(f1+f2+f3==Len2)
break;
}
printf("Case #%d: %d\n",T,((i<=Len1-Len2)?i:-1));
}
return 0;
}