UVA760
前言
这是一道 \(n\) 被经验,详见此帖子,但是这道题的数据很小所以理论上没这么难。
思路
一眼哈希,我们可以用双哈希处理出每一段的哈希值然后在通过相减二求出一个区间的值,然后我们可以二分答案为 \(mid\) 那么我们就可以进行检查。
重点在于如何写 check,其实很简单我们通过双哈希给一个字符串的每一段附上值然后再将每一段的值装入一个 map 中,然后我们对于另外的一个字符串进行枚举区间,然后求出其中的哈希值,再判断 map 中是否装有此值,如果有则返回可以,否则若枚举完所有的都没有合法的就只能缩短区间,最后我们能求出一个长度为 \(ans\)。
再单独跑一次 check 并将合法的区间变成字符串并装入 set 中输出即可。
代码
#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define fire signed
#define kong putchar(' ')
#define in(x) scanf("%lld",&x)
#define lcm(x,y) x*y/__gcd(x,y)
#define pb insert
#define w(x) while(x--)
#define il inline
il void print(int x) {
if(x>=10) print(x/10);
putchar(x%10+'0');
}
const int M=3100;
int H(int x,int y) {
return x<<32|y;
}
struct node{
string st;
int len;
int a[M];
int f[M],dp[M];
}s[5];
int n;
int jc[M],jci[M];
const int mod=998244353,Mod=2e6+3;
int get(int x,int l,int r) {
return (s[x].f[r]-s[x].f[l-1]*jc[r-l+1]%mod+mod)%mod;
}
int gets(int x,int l,int r) {
return (s[x].dp[r]-s[x].dp[l-1]*jci[r-l+1]%Mod+Mod)%Mod;
}
set<string>v;
bool check(int x) { //判断是否合法
unordered_map<int,int>mp;
rep(j,x,s[2].len) {
mp[H(get(2,j-x+1,j),gets(2,j-x+1,j))]++;
}
int res=0;
rep(j,x,s[1].len) {
res=0;
res+=mp.find(H(get(1,j-x+1,j),gets(1,j-x+1,j)))!=mp.end();
if(res==1) return 1;
}
return false;
}
void o(int x) { //记录答案
unordered_map<int,int>mp;
rep(j,x,s[2].len) {
mp[H(get(2,j-x+1,j),gets(2,j-x+1,j))]++;
}
int res=0;
rep(j,x,s[1].len) {
res=0;
res+=mp.find(H(get(1,j-x+1,j),gets(1,j-x+1,j)))!=mp.end();
if(res==1) {
string u="";
rep(i,j-x+1,j) u+=s[1].a[i]+'a'-1;
v.pb(u);
}
}
}
fire main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
jc[0]=jci[0]=1;
rep(i,1,1000) jc[i]=jc[i-1]*1331%mod,jci[i]=jci[i-1]*233%Mod;//预处理
string st;
int nj=0;
n=2;
while(cin>>s[1].st>>s[2].st) {
nj++;
if(nj>1) cout<<endl;
int p=false;
rep(i,1,n) {
s[i].len=false;
for(auto x:s[i].st) s[i].a[++s[i].len]=x-'a'+1;
rep(j,1,s[i].len) s[i].f[j]=(s[i].f[j-1]*1331%mod+s[i].a[j])%mod,s[i].dp[j]=(s[i].dp[j-1]*233%Mod+s[i].a[j])%Mod;//求出1到i的哈希值
p=max(p,s[i].len);
}
int l=1,r=p,res=0;
while(l<=r) {
int mid=l+r>>1;
if(check(mid)) l=mid+1,res=mid; //二分
else r=mid-1;
}
if(!res) {
cout<<"No common sequence.\n";
continue;
}
v.clear();
o(res);
for(auto x:v) cout<<x<<endl;
}
return false;
}

浙公网安备 33010602011771号