gym102861 C-Concatenating Teams 字符串hash
gym102861 C-Concatenating Teams
题意
给定两个集合\(A,B\),\(A\)和\(B\)中分别有\(n\)和\(m\)个字符串,每个集合中的字符串互不相同,将\(A\)中的字符串和\(B\)中的字符串两两按\(A\)在前\(B\)在后的顺序拼接,生成\(n\times m\)个字符串,得到集合\(C\),一个集合中的一个字符串是独特的当且仅当用它和另一个集合中的所有字符串拼接生成的字符串在\(C\)中都是唯一的,问\(A\)和\(B\)中分别有多少个独特的字符串。
分析
设字符串三元组\((x,x',S)\)满足\(x=x'S\),且\(x\)和\(x'\)都属于集合\(A\),三元组\((y,y',T)\)满足\(y=Ty'\),且\(y\)和\(y'\)都属于集合\(B\),能发现当\(S=T\)时,\(x,x',y,y'\)都不是独特的字符串,那么利用字符串\(hash+map\),就可以快速解决,具体实现看代码。
Code
#include<bits/stdc++.h>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define pii pair<int,int>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
const ull base=131;
map<ull,int>h1,h2;
map<ull,bool>v1,v2;
int n,m,len;
vector<ull>p,ha;
string s[N],t[N];
int a[N],b[N];
ull get(int l,int r)
{
return (ull)ha[r]-ha[l-1]*p[r-l+1];
}
void ins(string s)
{
len=s.size();
p.resize(len+1);ha.resize(len+1);
p[0]=1,ha[0]=0;
for(int i=1;i<=len;i++)
{
p[i]=p[i-1]*base;
ha[i]=ha[i-1]*base+(ull)s[i-1];
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
rep(i,1,n) cin>>s[i];
sort(s+1,s+n+1,[](string x,string y){return sz(x)<sz(y);});
rep(i,1,m) cin>>t[i];
sort(t+1,t+m+1,[](string x,string y){return sz(x)<sz(y);});
rep(i,1,n){
ins(s[i]);
h1[ha[len]]=i;
for(int j=1;j<len;j++) if(h1.count(ha[j])){
v1[get(j+1,len)]=1;
}
}
rep(i,1,m){
ins(t[i]);
h2[ha[len]]=i;
for(int j=1;j<len;j++) if(h2.count(get(j+1,len))){
v2[ha[j]]=1;
}
}
rep(i,1,n){
ins(s[i]);
for(int j=1;j<len;j++) if(h1.count(ha[j])&&v2.count(get(j+1,len))){
a[i]=a[h1[ha[j]]]=1;
}
}
rep(i,1,m){
ins(t[i]);
for(int j=1;j<len;j++) if(h2.count(get(j+1,len))&&v1.count(ha[j])){
b[i]=b[h2[get(j+1,len)]]=1;
}
}
int A=0,B=0;
rep(i,1,n) A+=(a[i]==0);
rep(i,1,m) B+=(b[i]==0);
cout<<A<<' '<<B<<endl;
return 0;
}