题目链接
看到题面发现还不是特别好推的,一开始想法O(N^2)肯定会T,所以就想到了用哈希,然后这道题又是找字符串中的子串,所以哈希直接找就是,我们找中间长度为x的字符串,是否在后面的查询字符串中出现过,若是出现过,说明此时的x还不一定是最优解,继续往下判断。
完整代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=1e5+7;
const ull Hash=1e9+7;
char s1[maxN], s2[maxN];
int len1, len2;
ull hash_1[maxN], hash_2[maxN], pre_hash[maxN], cnt, num_hash[maxN];
bool cmp(ull e1, ull e2) { return e1<e2; }
void pre_did()
{
memset(num_hash, 0, sizeof(num_hash));
hash_1[0]=0; hash_2[0]=0;
len1=(int)strlen(s1+1); len2=(int)strlen(s2+1);
for(int i=1; i<=len1; i++)
{
hash_1[i]=hash_1[i-1]*Hash+s1[i];
}
for(int i=1; i<=len2; i++)
{
hash_2[i]=hash_2[i-1]*Hash+s2[i];
}
}
int main()
{
pre_hash[0]=1;
for(int i=1; i<maxN; i++) pre_hash[i]=pre_hash[i-1]*Hash;
while(scanf("%s", s1+1)!=EOF)
{
getchar();
scanf("%s", s2+1);
pre_did();
int l=0, r=min(len1, len2), mid=0, ans=0;
while(l<=r)
{
mid=(l+r)>>1;
cnt=0;
for(int i=mid; i<=len1; i++)
{
num_hash[++cnt]=(hash_1[i] - hash_1[i-mid]*pre_hash[mid]); //剪去前面一部分,留下长度为mid的量
}
bool flag=false;
sort(num_hash+1, num_hash+1+cnt, cmp);
for(int i=mid; i<=len2; i++)
{
ull x=(hash_2[i] - hash_2[i-mid]*pre_hash[mid]);
if( *lower_bound(num_hash+1, num_hash+1+cnt, x) == x ) //若存存在这样的长度,说明目前长度并非最长值
{
flag=true;
break;
}
}
if(flag)
{
l=mid+1;
ans=mid;
}
else
{
r=mid-1;
}
}
printf("%d\n", ans);
getchar();
}
return 0;
}