题解: 我们考虑对第一个串建SAM 另一个串在第一个上跑 我们预处理出第一个串在parent树中以当前字符结尾产生的价值且下传到儿子节点 等于每个节点维护了 他在parent 树中到根这条链的所有子串的价值和 那么我们在来计算合并价值 第二串跑的时候 找到位置匹配的最远位置 而且我们必然可以得到他的祖先节点一定也会被匹配到 所以加上预处理的价值以及当前匹配的最远距离的价值 累积答案即可
/************************************************************** Problem: 4566 User: c20161007 Language: C++ Result: Accepted Time:1800 ms Memory:57152 kb ****************************************************************/ #include <bits/stdc++.h> const int MAXN=4e5+10; #define ll long long using namespace std; #define link(x) for(edge *j=h[x];j;j=j->next) int dis[MAXN],fa[MAXN],ch[MAXN][26],size[MAXN],sz[MAXN]; int cnt,cur,rt; char s1[MAXN],s2[MAXN]; bool vis[MAXN]; struct edge{int t;edge*next;}e[MAXN],*h[MAXN],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} void built(int x){ int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;size[cur]=1; for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur; if(!p)fa[cur]=rt; else{ int q=ch[p][x]; if(dis[p]+1==dis[q])fa[cur]=q; else{ int nt=++cnt;dis[nt]=dis[p]+1; memcpy(ch[nt],ch[q],sizeof(ch[q])); fa[nt]=fa[q];fa[q]=fa[cur]=nt; for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt; } } } int sa[MAXN],txt[MAXN]; void dfs(int x,int pre){ link(x){ if(j->t!=pre){dfs(j->t,x);size[x]+=size[j->t];} } } void slove(){ scanf("%s",s2+1);int t=strlen(s2+1);int temp=rt; ll ans=0;int len=0; for(int i=1;i<=t;i++){ int t=s2[i]-'a'; if(ch[temp][t])len++,temp=ch[temp][t]; else{ int p=temp; for(;p&&!ch[p][t];p=fa[p]); if(!p)temp=rt,len=0; else temp=ch[p][t],len=dis[p]+1; } if(temp!=rt)ans+=sz[fa[temp]]+1LL*size[temp]*max(0,len-dis[fa[temp]]); } printf("%lld ",ans); return ; } int main(){ scanf("%s",s1+1);int len=strlen(s1+1); rt=cnt=cur=1; for(int i=1;i<=len;i++)built(s1[i]-'a'); for(int i=1;i<=cnt;i++)add(fa[i],i); dfs(rt,0); for(int i=1;i<=cnt;i++)txt[dis[i]]++; for(int i=1;i<=cnt;i++)txt[i]+=txt[i-1]; for(int i=cnt;i>=1;i--)sa[txt[dis[i]]--]=i; for(int i=1;i<=cnt;i++)sz[sa[i]]=sz[fa[sa[i]]]+1LL*(dis[sa[i]]-dis[fa[sa[i]]])*size[sa[i]]; //for(int i=2;i<=cnt;i++)sz[i]=sz[fa[i]]+1LL*(dis[i]-dis[fa[i]])*size[i]; slove(); }
4566: [Haoi2016]找相同字符
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1109 Solved: 646
[Submit][Status][Discuss]
Description
给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。
Input
两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母
Output
输出一个整数表示答案
Sample Input
aabb
bbaa
bbaa
Sample Output
10