BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
题面
自己找去
HINT
给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种。我的思路是建立一个广义后缀自动机,对于每个节点记录\(size[1]和size[2]\)分别表示这个节点接受的子串在A中出现多少次,在B中出现多少次,然后\(ans=\sum_{u=2}^{tot}{size[u][1]*size[u][2]*(node[u].len-node[fa].len)}\)注意要long long
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<3)+(w<<1)+ch-48;
ch=getchar();
}
return w*f;
}
int n,m;
int size[800010][3];
struct SUFFIXAUTOMATON{
struct Node{
int fa,len;
map<int,int> ch;
}node[800010];
int lst,tot,root;
inline void init(){
lst=tot=root=1;return;
}
inline void extend(int now,int id){
int p=lst;tot++;lst=tot;int np=tot;
node[np].len=node[p].len+1;size[np][id]=1;
while(p&&!node[p].ch[now]){
node[p].ch[now]=np;
p=node[p].fa;
}
if(!p) node[np].fa=1;
else{
int q=node[p].ch[now];
if(node[q].len==node[p].len+1){
node[np].fa=q;
}
else{
int nq=++tot;node[nq]=node[q];
node[nq].len=node[p].len+1;
node[q].fa=nq;node[np].fa=nq;
while(p&&node[p].ch[now]==q){
node[p].ch[now]=nq;
p=node[p].fa;
}
}
}
}
}SAM;
int cnt,head[800010];
struct Edge{
int from,to,next;
}edge[1600010];
inline void addedge(int u,int v){
cnt++;
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
char ch[200010];
inline void dfs(int u){
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;dfs(v);
size[u][1]+=(long long)size[v][1];
size[u][2]+=(long long)size[v][2];
}
return;
}
long long ans;
signed main(){
SAM.init();
for(int i=1;i<=2;i++){
cin>>ch;int len=strlen(ch);
for(int j=0;j<len;j++){
SAM.extend(ch[j]-'a'+1,i);
}
SAM.lst=1;
}
for(int i=2;i<=SAM.tot;i++){
addedge(SAM.node[i].fa,i);
}
dfs(1);
//cout<<SAM.tot<<endl;
for(int i=2;i<=SAM.tot;i++){
int f=SAM.node[i].fa;
//cout<<(long long)size[i][1]*size[i][2]<<" "<<SAM.node[i].len-SAM.node[f].len<<endl;
long long cur1=(long long)size[i][1]*size[i][2];long long cur2=(long long)SAM.node[i].len-SAM.node[f].len;
//cout<<cur1<<" "<<cur2<<endl;
ans+=(long long)cur1*cur2;
}
cout<<ans<<endl;
return 0;
}