HDU 5343 MZL's Circle Zhou(后缀自动机+记忆化搜索)
2018-03-25 17:08
585 查看
MZL's Circle Zhou
TimeLimit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 506 Accepted Submission(s): 212
Problem Description
MZL's Circle Zhou is good at solving some counting problems. One day, he comes up with a counting problem:
You are given two strings
a,b
which consist of only lowercase English letters. You can subtract a substring
x
(maybe empty) from string
a
and a substring y
(also maybe empty) from string
b,
and then connect them as
x+y
with x
at the front and y
at the back. In this way, a series of new strings can be obtained.
The question is how many different new strings can be obtained in this way.
Two strings are different, if and only if they have different lengths or there exists an integer
i
such that the two strings have different characters at position
i.
Input
The first line of the input is a single integer
T (T≤5),
indicating the number of testcases.
For each test case, there are two lines, the first line is string
a,
and the second line is string
b.
1<=|a|,|b|<=90000.
Output
For each test case, output one line, a single integer indicating the answer.
Sample Input
2acbcccccabcbbbabbababbababbaaaabbbbabbaaaabaabbabbabbbaaabaababbaabbabbaaaabbbaababbabbabababaaaaabbaabbaabbaab
Sample Output
135557539
Author
SXYZ
Source
2015 Multi-University Training Contest 5
大致题意,给你两个字符串,然后从第一个字符串里面取出一个子串X,从第二个字符串里面取出一个子串Y,两个拼接在一起组成新的字符串,其中X、Y都可以是空串,问有多少个这样不同的串。
如果整体来思考不同的X+Y的个数,会发现找不到突破口。我们可以考虑X+Y为什么会有重复的。举个例子ababc,可以由ab+abc或则a+babc组成。重复的原因在于在第一个串中可以找到ab,也可以找到a,而如果a可以构成这个拼接串,那么ab也构成这个拼接串。所以说,为了避免重复,我们可以在第一个串中找最长的点,即走到某个点x,然后这个点不能走到字符'a',那么对于字符'a'来说,x这个点就是最长的,在另一个串中找'a'开头的子串个数,这些就是点x的可以匹配到的个数。
具体来说,对于两个子串各自建立后缀自动机,利用后缀自动机保存所有子串的性质。先在第一个自动机上面遍历,遍历到一个不能走到一个特定字符的点,然后再到另一个自动机上遍历找到以该特定字符开头的所有子串个数。这个个数就是这一个节点的贡献。统计所有的贡献和即可。
由于是两个自动机,然后涉及到相互的遍历,所以如果直接暴力遍历,复杂度可以退化到O(N^2)。但是考虑到不同时期遍历同一个点的贡献相同,所以我们可以用记忆化搜索来把保存贡献,每个点只需要计算一次,做到O(N)复杂度。另外,本题数据量较大,需要用到unsigned long long。具体见代码:
#include<bits/stdc++.h> #define LL unsigned long long #define N 200010 using namespace std; struct Suffix_Automation { int tot,cur,n,c ,sa ,right ; struct node{int ch[26],len,fa;} T ; void init(){cur=tot=1;memset(T,0,sizeof(T));} void ins(int x,int id) { int p=cur;cur=++tot;T[cur].len=id;right[cur]++; for(;p&&!T[p].ch[x];p=T[p].fa) T[p].ch[x]=cur; if (!p) {T[cur].fa=1;return;}int q=T[p].ch[x]; if (T[p].len+1==T[q].len) {T[cur].fa=q;return;} int np=++tot; memcpy(T[np].ch,T[q].ch,sizeof(T[q].ch)); T[np].fa=T[q].fa; T[q].fa=T[cur].fa=np; T[np].len=T[p].len+1; for(;p&&T[p].ch[x]==q;p=T[p].fa) T[p].ch[x]=np; } } X,Y; char s1 ,s2 ; LL dp1 ,dp2 ; LL dfs2(int x) { if (!x) return 0; LL res=1; if (dp2[x]) return dp2[x]; for(int i=0;i<26;i++) { int nxt=Y.T[x].ch[i]; if (nxt) res+=dfs2(nxt); } return dp2[x]=res; } LL dfs1(int x) { LL res=1; if (dp1[x]) return dp1[x]; for(int i=0;i<26;i++) { int nxt=X.T[x].ch[i]; if (nxt) res+=dfs1(nxt); else res+=dfs2(Y.T[1].ch[i]); } return dp1[x]=res; } int main() { int T_T; cin>>T_T; while(T_T--) { X.init(); Y.init(); scanf("%s%s",s1,s2); memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); for(int i=0;s1[i];i++) X.ins(s1[i]-'a',i+1); for(int i=0;s2[i];i++) Y.ins(s2[i]-'a',i+1); printf("%I64u\n",dfs1(1)); } }
相关文章推荐
- Hdu 5343 MZL's Circle Zhou 后缀自动机
- hdu 5343 MZL's Circle Zhou(后缀自动机)
- 【HDU】5343 MZL's Circle Zhou【后缀自动机】
- HDU 5343 MZL's Circle Zhou【后缀自动机】
- HDOJ 5343 MZL's Circle Zhou 后缀自动机
- hdu 5343 MZL's Circle Zhou(后缀自动机)
- HDU 5343 MZL's Circle Zhou 后缀自动机+DP
- HDU 5343(MZL's Circle Zhou-SAM)[Template:SAM]
- HDU 4622 Reincarnation 后缀数组 或 后缀自动机
- 后缀自动机1003 HDU 4416
- hdu 4622(后缀自动机|后缀数组)
- 字符串(后缀自动机):HDU 4622 Reincarnation
- HDU 5442 后缀自动机+kmp
- hdu 4416 后缀自动机 问在S中有多少个不同子串满足它不是s1~sn中任意一个字符串的子串
- Hdu 4436 str2int 后缀自动机
- HDU 4622 多校第三场1002 后缀自动机
- HDU 5853 Jong Hyok and String(二分+后缀数组/广义后缀自动机)
- HDU 5558 Alice's Classified Message 后缀自动机
- HDU 4436 str2int(后缀自动机)
- HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机