P7081 题解
stardust_Ray · · 题解
简要题意:给你串
首先
我们枚举
但我们仔细阅读题目,发现
如果用 map 实现,时间复杂度
#define LJY main
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2005;
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
const int TMP=rnd();
const int B=((rnd()>>11)<<7)|(rnd()&127)|3; // 随机 base,自然溢出
ull pw[N];string S,T;
struct Hsh{ // 哈希值
int len;ull v;
Hsh(){len=v=0;}
Hsh(char x){len=1;v=x;}
Hsh(int _l,ull _v):len(_l),v(_v){}
bool operator<(const Hsh b)const{
if(len!=b.len) return len<b.len;
return v<b.v;
}
}ss[N],st[N],fs[N][N],ft[N][N];
inline Hsh operator+(Hsh a,Hsh b){
return {a.len+b.len,a.v*pw[b.len]+b.v};}
inline Hsh hsh1(int l,int r){
if(l>r) return Hsh();
return {r-l+1,ss[r].v-ss[l-1].v*pw[r-l+1]};}
inline Hsh hsh2(int l,int r){
if(l>r) return Hsh();
return {r-l+1,st[r].v-st[l-1].v*pw[r-l+1]};}
unordered_map<ull,int>mp;
map<Hsh,pair<int,int> >Mp;
void clear(unordered_map<ull,int>&x){
unordered_map<ull,int>y;x.swap(y);}
signed LJY(){
pw[0]=1;For(i,1,N-1) pw[i]=pw[i-1]*B;
ios::sync_with_stdio(0);cin.tie(0);
getline(cin,S);getline(cin,T);
int n=S.size(),m=T.size();S=' '+S;T=' '+T;
For(i,1,n) ss[i]=ss[i-1]+S[i];
For(i,1,m) st[i]=st[i-1]+T[i];
int ans=n+m;pair<int,int>U,V;
U={1,n};V={1,m};
For(len,1,n){
For(l,1,n-len+1) fs[l][l+len-1]='*'+hsh1(l+len,n);
clear(mp);
ForDown(l,n-len+1,1){
mp[hsh1(l,l+len-1).v]=l;Hsh tmp=hsh1(l-len,l-1);
if(l-len>0&&mp.count(tmp.v)){
int pos=mp[tmp.v]; // 用 unordered_map 找到下一个出现的位置,转移 g
fs[l-len][l-1]='*'+hsh1(l,pos-1)+fs[pos][pos+len-1];
}
}
for(auto [_,x] within mp){ // 还留在 map 里的是可以成为最终哈希值的
int r=x+len-1;
fs[x][r]=hsh1(1,x-1)+fs[x][r]; // 加上一段前缀,计算出 f
if(!Mp.count(fs[x][r])) Mp[fs[x][r]]={x,len}; // 放到 map 中便于后面查询
}
}
For(len,1,m){
For(l,1,m-len+1) ft[l][l+len-1]='*'+hsh2(l+len,m);
clear(mp);
ForDown(l,m-len+1,1){
mp[hsh2(l,l+len-1).v]=l;Hsh tmp=hsh2(l-len,l-1);
if(l-len>0&&mp.count(tmp.v)){
int pos=mp[tmp.v];
ft[l-len][l-1]='*'+hsh2(l,pos-1)+ft[pos][pos+len-1]; //同上
}
}for(auto [_,l] within mp){
int r=l+len-1;
ft[l][r]=hsh2(1,l-1)+ft[l][r]; // 同上
if(Mp.count(ft[l][r])){
auto [L,ln]=Mp[ft[l][r]];
int res=ln+r-l+1; // 查询答案
if(res<ans) ans=res,U={L,L+ln-1},V={l,r};
}
}
}
// -- T 非空的情况 ⬆
// -- T 为空串的情况 ⬇
For(len,1,n){
For(l,1,n-len+1) fs[l][l+len-1]=hsh1(l+len,n);
clear(mp);
ForDown(l,n-len+1,1){
mp[hsh1(l,l+len-1).v]=l;
if(l-len>0&&mp.count(hsh1(l-len,l-1).v)){
int pos=mp[hsh1(l-len,l-1).v];
fs[l-len][l-1]=hsh1(l,pos-1)+fs[pos][pos+len-1]; // 不用加特殊字符
}
}
for(auto [_,x] within mp){
int r=x+len-1;
fs[x][r]=hsh1(1,x-1)+fs[x][r];
if(fs[x][r].len==m&&fs[x][r].v==st[m].v){ // 和 B 串比较
if(ans>len) ans=len,U={x,r},V={1,0};
}
}
}
printf("s/");
For(i,U.first,U.second) putchar(S[i]);putchar('/');
For(i,V.first,V.second) putchar(T[i]);putchar('/');putchar('g');
return 0;
}
不知道我是怎么把小清新题写成【数据删除】的。