[CF1535F]String Distance

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1535F]String Distance相关的知识,希望对你有一定的参考价值。

String Distance

题解

《关于因为卡模数所以被笔者称之为"贞卡模"的那件事》
都在test61WA了,是jzm的错吗
在这里插入图片描述

test 5与test 6混入其中

首先我们可以考虑 f ( s i , s j ) f(s_{i},s_{j}) f(si,sj)的值。

  • 当两者某个字符的数量不同时,两者永远变不一起去,代价为 1337 1337 1337奇怪的数字
  • 当两者有差异的子串间有一个是有序的,我们只需要排一个,代价为 1 1 1
  • 当两者有差异的子串都是无序的时,我们需要将两者都排一遍序,代价为 2 2 2
  • 当两者没有差异时,代价为 0 0 0

第一种与第四种可以直接用hash求出,关键是第二种与第三种该怎么求。
我们可以考虑将所有的字符串串按每种字符的数量分类,再通过基排排一遍序。
此时就跟后缀数组一样,我们得到的相邻的两个字符串的 l c p lcp lcp一定是最大的。
我们考虑对于每个字符串划分出它的极大有序区间,与贡献为 1 1 1的两个串的差异子串一定是两者中其中一个极大有序区间的子区间。
当字符串是按从大到小的方法排列时,拥有差异子串部分是有序那一个串一定是在最后的。

对于其它串,当且仅当除该有序区间的部分都相同时才会贡献为 1 1 1
对于前半部分,由于前缀相同的子串是连续的,我们可以通过二分找到与其极大有序区间的前缀相同的子串的区间。
字符串比较的部分我们可以通过字符串Hash来做到 O ( 1 ) O\\left(1\\right) O(1)
而后缀部分,我们可以通过可持久化 T r i e Trie Trie树来维护。
我们将每个后缀的Hash值都加入 T r i e Trie Trie树中,用差分的方法买得到前缀相同的区间中,后缀也与它相同的串的数量。
这些串与该串的贡献为 1 1 1,而该类其余的串与其贡献为 2 2 2,其它类的串与其贡献为 1337 1337 1337
对于完全相同的串,排序后一定是连续的,我们可以先二分找到,计算前三类贡献时就先将其排除掉,免得之后还要计算极大有序区间数量太麻烦。

由于我们要 H a s h Hash Hash的部分实在太多,避免重复,我们得采用三哈希。还得疯狂调模数
但我们可以发现,由于 n ⋅ ∣ s 1 ∣ ⩽ 2 × 1 0 5 n\\cdot|s1|\\leqslant 2\\times 10^5 ns12×105,字符串较长的串,串的数量其实很少,串数量多的其实是串长很少的串。
但如果对于较短的串还要三哈希跑 90 90 90层实在太麻烦了,所以对于这部分串,我们可以直接建 T r i e Trie Trie树出来。
这样常数会稍微小一点。

时间复杂度 O ( n ∣ s ∣ l o g   n ) O\\left(n|s|log\\,n\\right) O(nslogn)但模数贞德很难调

源码

卡了半天,最后发现竟然是因为 j z m jzm jzm不能赋 233333 233333 233333,果然是因为 j z m jzm jzm太强了。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mod1=998244353;
const int mod2=1e9+7;
const int mod3=1e9+9;
const int iv2=5e8+4;
const int lim=1000000;
const int jzm=1e6+7;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
int n,sum,num[30],tot,id[MAXN],n1,root[MAXN];LL ans;
char str[MAXN],ss[10];
struct hashnode{
	int fir,sec,tri;
	int ask(int dep){
		if(dep>=60)return (fir>>dep-60)&1;
		if(dep>=30)return (sec>>dep-30)&1;
		return (tri>>dep)&1;
	}
	bool operator == (const hashnode &rhs)const{
		return fir==rhs.fir&&sec==rhs.sec&&tri==rhs.tri;
	}
}suf[MAXN],pre[MAXN];
struct ming{int st,ed,len,hs;}a[MAXN];
struct node{int ch[2],sum;};
struct node1{int ch[30],sum;};
vector<int>vec[MAXN],tp[30];
map<int,int>mp;
class TrieTree{
	public:
		int tot;node tr[MAXN*90];
		void clear(){tot=0;tr[0].sum=tr[0].ch[0]=tr[0].ch[1]=0;}
		void insert(int &now,int las,hashnode val,int dep=89){
			if(now==las||!now)tr[now=++tot]=tr[las];
			if(dep<0){tr[now].sum++;return ;}
			if(val.ask(dep))insert(tr[now].ch[1],tr[las].ch[1],val,dep-1);
			else insert(tr[now].ch[0],tr[las].ch[0],val,dep-1);
		}
		int query(int rt,hashnode val,int dep=89){
			if(!rt)return 0;if(dep<0)return tr[rt].sum;
			if(val.ask(dep))return query(tr[rt].ch[1],val,dep-1);
			return query(tr[rt].ch[0],val,dep-1);
		}
}T;
class superTrie{
	public:
		int tot;node1 tr[MAXN*10];
		void clear(){tot=0;tr[0].sum=tr[0].ch[0]=tr[0].ch[1]=0;}
		void insert(int &now,int las,int dep){
			if(now==las||!now)tr[now=++tot]=tr[las];
			if(dep<0){tr[now].sum++;return ;}
			insert(tr[now].ch[ss[dep]-'a'],tr[las].ch[ss[dep]-'a'],dep-1);
		}
		int query(int rt,int dep){
			if(!rt)return 0;if(dep<0)return tr[rt].sum;
			return query(tr[rt].ch[ss[dep]-'a'],dep-1);
		}
}T1;
bool compare(int x,int y,int len){if(!len)return 1;return pre[len+a[x].st-1]==pre[len+a[y].st-1];}
void modify(int i,int l,int r){
	if(n1>9)T.insert(root[i],root[i-1],suf[l]);
	else{
		for(int j=0;j<n1;j++)ss[j]=0;
		int sm=0;for(int j=l;j<r;j++)ss[sm++]=str[j];
		T1.insert(root[i],root[i-1],sm-1);
	}
}
int found(int i,int l,int r){
	if(n1>9)return T.query(root[i],suf[l]);
	else{
		for(int j=0;j<n1;j++)ss[j]=0;
		int sm=0;for(int j=l;j<r;j++)ss[sm++]=str[j];
		return T1.query(root[i],sm-1);
	}
}
signed main(){
	read(n);
	for(int i=1;i<=n;i++){
		scanf("\\n%s",str+sum);a[i].st=sum;
		a[i].len=(int)strlen(str+sum);sum+=a[i].len;n1=a[i].len;a[i].ed=sum;
		for(int j=1;j<=26;j++)num[j]=0;
		for(int j=0;j<a[i].len;j++)num[str[j+a[i].st]-'a'+1]++;
		for(int j=1;j<=26;j++)a[i].hs=(1ll*jzm*a[i].hs+1ll*num[j])%mod1;
		if(n1>9)for(int j=n1-1;j>=0;j--)
			suf[j+a[i].st].fir=(31ll*suf[jCF161D Distance in Tree

[CF1032D] Barcelonian Distance - 计算几何

[CF1032D] Barcelonian Distance - 计算几何

CF161D Distance in Tree |点分治

[CF442E]Gena and Second Distance

CF&&CC百套计划2 CodeChef December Challenge 2017 Chef and Hamming Distance of arrays