题意:
给出n个字符串,长度均为len;
有m次操作,每次将两个字符交换;
求每个字符串在任何时点上,与相同的它最多的字符串个数;
n<=1000,len<=100,m<=100000;
题解:
Poi!
字符串长度很小,我们先考虑到用Hash来判断字符串的相同;
这些部分很简单,但是统计任意时点对某个字符串的答案是很难的;
因为如果暴力更新的话复杂度是O(nm),所以不能这么搞;
而延迟更新也没有什么好办法,只能去找打标记的数据结构了;
这里我写了一个Splay,以Hash值大小为关键字排序;
修改时先将其转到根删掉,然后再修改之后插回去,
之后将Hash值相同的一段提出来打标记更新答案;
这样每次的复杂度是O(len+logn)的。。
注意将同一个字符串中的字符交换时,不要让它被删两次哦2333;
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1100
#define seed 1331
#define which(x) (ch[fa[x]][1]==x)
using namespace std;
typedef unsigned long long ll;
int n,len;
int size[N],fa[N],ch[N][2],cov[N],ans[N],root;
char str[N][111];
ll val[N],pow[111];
void Pushup(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void Pushdown(int x)
{
if(cov[x])
{
ans[ch[x][0]]=max(ans[ch[x][0]],cov[x]);
cov[ch[x][0]]=max(cov[ch[x][0]],cov[x]);
ans[ch[x][1]]=max(ans[ch[x][1]],cov[x]);
cov[ch[x][1]]=max(cov[ch[x][1]],cov[x]);
cov[x]=0;
}
}
void Rotate(int x)
{
int f=fa[x];
bool k=which(x);
Pushdown(f),Pushdown(x);
ch[f][k]=ch[x][!k];
ch[x][!k]=f;
ch[fa[f]][which(f)]=x;
fa[x]=fa[f];
fa[f]=x;
fa[ch[f][k]]=f;
Pushup(f);
Pushup(x);
}
void Splay(int x,int g)
{
while(fa[x]!=g)
{
int f=fa[x];
if(fa[f]==g)
{
Rotate(x);
break;
}
if(which(x)^which(f))
Rotate(x);
else
Rotate(f);
Rotate(x);
}
if(!g) root=x;
}
int pre(ll v)
{
int p=root,ret=root;
while(p)
{
if(v>val[p])
ret=p,p=ch[p][1];
else
p=ch[p][0];
}
return ret;
}
int sub(ll v)
{
int p=root,ret;
while(p)
{
if(v<val[p])
ret=p,p=ch[p][0];
else
p=ch[p][1];
}
return ret;
}
void Down(int x)
{
if(!x) return ;
Pushdown(x);
Down(ch[x][0]);
Down(ch[x][1]);
}
void Insert(int x)
{
int l=pre(val[x]),r=sub(val[x]);
Splay(l,0),Splay(r,l);
int t=ch[r][0];
fa[t]=x,ch[x][0]=t;
fa[x]=r,ch[r][0]=x;
Pushup(x),Pushup(r),Pushup(l);
ans[x]=max(ans[x],size[x]);
cov[x]=max(cov[x],size[x]);
}
void del(int x)
{
Splay(x,0);
int p=ch[x][1];
while(ch[p][0])
p=ch[p][0];
Splay(p,x);
ch[p][0]=ch[x][0];
fa[ch[p][0]]=p,fa[p]=0;
root=p;
Pushup(p);
ch[x][0]=ch[x][1]=0;
size[x]=1;
}
void init()
{
pow[0]=1;
for(int i=1;i<=len;i++)
pow[i]=pow[i-1]*seed;
root=n+1,size[n+1]=2,ch[n+1][1]=n+2;
size[n+2]=1,fa[n+2]=n+1;
val[n+1]=0,val[n+2]=(1ll<<64)-1;
}
int main()
{
int m,i,j,k,a,b,x,y;
scanf("%d%d%d",&n,&len,&m);
init();
for(i=1;i<=n;i++)
{
scanf("%s",str[i]+1);
for(j=1;j<=len;j++)
val[i]=val[i]*seed+str[i][j];
Insert(i);
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&a,&y,&b);
if(x==y)
{
del(x);
swap(str[x][a],str[x][b]);
for(j=1,val[x]=0;j<=len;j++)
val[x]=val[x]*seed+str[x][j];
Insert(x);
continue;
}
del(x),del(y);
swap(str[x][a],str[y][b]);
for(j=1,val[x]=val[y]=0;j<=len;j++)
val[x]=val[x]*seed+str[x][j],
val[y]=val[y]*seed+str[y][j];
Insert(x),Insert(y);
}
Down(root);
for(i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}