您的位置:首页 > 其它

bzoj4566【HAOI2016】找相同字符

2016-06-29 00:10 239 查看

4566: [Haoi2016]找相同字符

Time Limit: 20 Sec Memory Limit: 256 MB

Submit: 128 Solved: 75

[Submit][Status][Discuss]

Description

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

Input

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

Output

输出一个整数表示答案

Sample Input

aabb

bbaa

Sample Output

10

广义后缀自动机
建立两个串的后缀自动机,统计一下每个节点的两个串出现次数sz[i][0]和sz[i][1],则答案等于∑(mx[i]-mx[fa[i]])*sz[i][0]*sz[i][1]。
另外一个小细节就是拓扑排序的地方要注意一下。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define N 200005
#define M 800005
using namespace std;
int n,m,cnt=1,last;
int fa[M],mx[M],c[M][26],sz[M][2],v
,q[M];
ll ans;
char a
,b
;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int d[M];
queue<int> qu;
void calc()
{
//	F(i,1,cnt) v[mx[i]]++;
//	F(i,1,max(n,m)) v[i]+=v[i-1];
//	F(i,1,cnt) q[v[mx[i]]--]=i; //这样也是对的
int tmp=cnt;
F(i,1,cnt) d[fa[i]]++;
F(i,1,cnt) if (!d[i]) qu.push(i);
while (!qu.empty())
{
int x=qu.front();qu.pop();
q[tmp--]=x;d[fa[x]]--;
if (!d[fa[x]]) qu.push(fa[x]);
}
D(i,cnt,1)
{
sz[fa[q[i]]][0]+=sz[q[i]][0];
sz[fa[q[i]]][1]+=sz[q[i]][1];
}
F(i,1,cnt) ans+=(ll)(mx[i]-mx[fa[i]])*sz[i][0]*sz[i][1];
}
void add(int x)
{
int p=last;
if (c[p][x]&&mx[c[p][x]]==mx[p]+1){last=c[p][x];return;}
int np=++cnt;last=np;
mx[np]=mx[p]+1;
while (p&&!c[p][x]) c[p][x]=np,p=fa[p];
if (!p) fa[np]=1;
else
{
int q=c[p][x];
if (mx[q]==mx[p]+1) fa[np]=q;
else
{
int nq=++cnt;
mx[nq]=mx[p]+1;
memcpy(c[nq],c[q],sizeof(c[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
while (p&&c[p][x]==q) c[p][x]=nq,p=fa[p];
}
}
}
int main()
{
scanf("%s",a+1);scanf("%s",b+1);
n=strlen(a+1);m=strlen(b+1);
last=1;F(i,1,n) add(a[i]-'a'),sz[last][0]++;
last=1;F(i,1,m) add(b[i]-'a'),sz[last][1]++;
calc();
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: