正题
题目大意
两个字符串A,BA,BA,B。可以修改AAA中的一个字符使得AAA中的1∼k1\sim k1∼k是BBB的子串,求kkk的最大值。
解题思路
先将AAA和BBB字符串hashhashhash,然后枚举BBB作为子串的起始位置,然后二分出不修改字符的第一个不相等处xxx,然后从x+1x+1x+1个字符继续开始二分,也就是表示跳过xxx这个字符。
时间复杂度O(nlogn)O(n\ log\ n)O(n log n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const int N=51000,p=233;
char a[N],b[N];
int n1,n2,maxs;
ull pow[N],hash1[N],hash2[N];
ull get_hash1(int l,int r)
{return hash1[r]-hash1[l-1]*pow[r-l+1];}
ull get_hash2(int l,int r)
{return hash2[r]-hash2[l-1]*pow[r-l+1];}
int main()
{scanf("%s",a+1);n1=strlen(a+1);scanf("%s",b+1);n2=strlen(b+1);pow[0]=1;for(int i=1;i<=n1;i++){pow[i]=pow[i-1]*p;hash1[i]=hash1[i-1]*p+a[i]-'a';}for(int i=1;i<=n2;i++)hash2[i]=hash2[i-1]*p+b[i]-'a';for(int i=1;i<=n2;i++){int ans,l=0,r=min(n1,n2-i+1);while(l<=r){int mid=(l+r)/2;if(hash1[mid]==get_hash2(i,i+mid-1)) l=mid+1;else r=mid-1;}ans=r+1;l=r+1;r=min(n1,n2-i+1);while(l<=r){int mid=(l+r)/2;if(get_hash1(ans+1,mid)==get_hash2(i+ans,i+mid-1)) l=mid+1;else r=mid-1;}maxs=max(maxs,r);}printf("%d",maxs);
}