您的位置:首页 > 其它

BZOJ4566: [Haoi2016]找相同字符

2016-06-01 16:39 330 查看

Description

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。

Input

两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母

Output

输出一个整数表示答案

Sample Input

aabb

bbaa

Sample Output

10

裸题,用SAM来做的话先建出第一个串的后缀自动机,把第二个串拿上去运行,不完整节点直接计算,完整节点打个懒标记最后扫一遍就行了。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=400010;
int to[maxn][26],l[maxn],fa[maxn],last=1,cnt=1;
int f[maxn],siz[maxn],od[maxn],c[maxn];
void extend(int c) {
int p,q,np,nq;p=last;l[last=np=++cnt]=l[p]+1;siz[np]=1;
for(;!to[p][c];p=fa[p]) to[p][c]=np;
if(!p) fa[np]=1;
else {
q=to[p][c];
if(l[p]+1==l[q]) fa[np]=q;
else {
l[nq=++cnt]=l[p]+1;
fa[nq]=fa[q];fa[q]=fa[np]=nq;
memcpy(to[nq],to[q],sizeof(to[nq]));
for(;to[p][c]==q;p=fa[p]) to[p][c]=nq;
}
}
}
char s[maxn];
int main() {
scanf("%s",s);
for(int i=0;s[i];i++) extend(s[i]-'a');
scanf("%s",s);
int p=1,len=0;ll ans=0;
rep(i,1,cnt) c[l[i]]++;
rep(i,1,cnt) c[i]+=c[i-1];
dwn(i,cnt,1) od[c[l[i]]--]=i;
dwn(i,cnt,1) siz[fa[od[i]]]+=siz[od[i]];
for(int i=0;s[i];i++) {
int c=s[i]-'a';
if(to[p][c]) len++,p=to[p][c];
else {
while(p&&!to[p][c]) p=fa[p];
if(p) len=l[p]+1,p=to[p][c];
else p=1,len=0;
}
ans+=(ll)siz[p]*(len-l[fa[p]]);f[fa[p]]++;
}
dwn(i,cnt,1) {
int x=od[i];f[fa[x]]+=f[x];
ans+=(ll)f[x]*siz[x]*(l[x]-l[fa[x]]);
}
printf("%lld\n",ans);
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: