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
2
acbcc
cccabc
bbbabbababbababbaaaabbbbabbaaaabaabbabbabbbaaabaab
abbaabbabbaaaabbbaababbabbabababaaaaabbaabbaabbaab
 
Sample Output
135
557539
 
Author
SXYZ
 
Source
2015 Multi-University Training Contest 5
 
题解:题目意思给你两个字符串,然后从第一个字符串里面取出一个子串X,从第二个字符串里面取出一个子串Y,两个拼接在一起组成新的字符串,其中X、Y都可以是空串,问有多少个这样不同的串。
思路:考虑X+Y为什么会有重复的。举个例子ababc,可以由ab+abc或则a+babc组成。重复的原因在于在第一个串中可以找到ab,也可以找到a,而如果a可以构成这个拼接串,那么ab也构成这个拼接串。所以说,为了避免重复,我们可以在第一个串中找最长的点,即走到某个点x,然后这个点不能走到字符'a',那么对于字符'a'来说,x这个点就是最长的,在另一个串中找'a'开头的子串个数,这些就是点x的可以匹配到的个数。(用记忆化搜索)

 

参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define RI register int
const int maxn=1e5+;
char s1[maxn],s2[maxn];
struct SAM{
int last,tot,nxt[maxn<<][],fa[maxn<<],l[maxn<<];
inline void Init()
{
last=tot=;
memset(nxt[tot],,sizeof(nxt[tot]));
l[tot]=fa[tot]=;
}
inline int NewNode()
{
++tot;
memset(nxt[tot],,sizeof(nxt[tot]));
l[tot]=fa[tot]=;
return tot;
}
inline void Add(int c)
{
int np=NewNode(),p=last;
last=np;l[np]=l[p]+;
while(p&&!nxt[p][c]) nxt[p][c]=np,p=fa[p];
if(!p) fa[np]=;
else
{
int q=nxt[p][c];
if(l[q]==l[p]+) fa[np]=q;
else
{
int nq=NewNode();
memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
fa[nq]=fa[q];
l[nq]=l[p]+;
fa[q]=fa[np]=nq;
while(p&&nxt[p][c]==q) nxt[p][c]=nq,p=fa[p];
}
}
}
} sam1,sam2; int T;
ull dp1[maxn<<],dp2[maxn<<];
inline ull dfs2(int u)
{
if(!u) return ;
if(dp2[u]) return dp2[u];
ull res=;
for(int i=;i<;++i)
{
int nt=sam2.nxt[u][i];
if(nt) res+=dfs2(nt);
}
return dp2[u]=res;
}
inline ull dfs(int u)
{
if(dp1[u]) return dp1[u];
ull res=;
for(int i=;i<;++i)
{
int nt=sam1.nxt[u][i];
if(nt) res+=dfs(nt);
else res+=dfs2(sam2.nxt[][i]);
}
return dp1[u]=res;
} int main()
{
scanf("%d",&T);
while(T--)
{
sam1.Init();sam2.Init();
memset(dp1,,sizeof dp1);
memset(dp2,,sizeof dp2); scanf("%s%s",s1,s2);
for(int i=;s1[i];++i) sam1.Add(s1[i]-'a');
for(int i=;s2[i];++i) sam2.Add(s2[i]-'a'); printf("%I64u\n",dfs());
} return ;
}

HDU5343 MZL's Circle Zhou(SAM+记忆化搜索)的更多相关文章

  1. HDU5343:MZL's Circle Zhou(SAM,记忆化搜索DP)

    Description Input Output Sample Input Sample Output Solution 题意:给你两个串,分别从两个里面各选出一个子串拼到一起,问能构成多少个本质不同 ...

  2. hdu 5343 MZL's Circle Zhou SAM

    MZL's Circle Zhou 题意:给定两个长度不超过a,b(1 <= |a|,|b| <= 90000),x为a的连续子串,b为y的连续子串(x和y均可以是空串):问x+y形成的不 ...

  3. [HDU5343]MZL's Circle Zhou

    题目大意: 给你两个字符串a和b,从中分别取出子串x和y,求不同的x+y的个数. 思路: 对于每一个字符串,构建SAM. 为了保证相同的x+y不会被重复统计,我们可以想办法只统计相同的x+y中x最长的 ...

  4. HDU 5343 MZL's Circle Zhou 后缀自动机+DP

    MZL's Circle Zhou Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  5. HDU 5343 MZL's Circle Zhou

    MZL's Circle Zhou Time Limit: 1000ms Memory Limit: 131072KB This problem will be judged on HDU. Orig ...

  6. Codeforces Round #406 (Div. 1) A. Berzerk 记忆化搜索

    A. Berzerk 题目连接: http://codeforces.com/contest/786/problem/A Description Rick and Morty are playing ...

  7. HDU 1208 Pascal's Travels 经典 跳格子的方案数 (dp或者记忆化搜索)

    Pascal's Travels Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Su ...

  8. POJ 2704 Pascal's Travels 【DFS记忆化搜索】

    题目传送门:http://poj.org/problem?id=2704 Pascal's Travels Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  9. [ACM_动态规划] 数字三角形(数塔)_递推_记忆化搜索

    1.直接用递归函数计算状态转移方程,效率十分低下,可以考虑用递推方法,其实就是“正着推导,逆着计算” #include<iostream> #include<algorithm> ...

随机推荐

  1. Convolutional Sequence to Sequence Learning 论文笔记

    目录 简介 模型结构 Position Embeddings GLU or GRU Convolutional Block Structure Multi-step Attention Normali ...

  2. dubbo中出现can not be invoked any more

    具体错误示例如下 从错误看,是客户方发起调用时,dubbo会去检查本地的invoker instance,如果发现invoker已经是destroy status,则直接抛出上面的异常,下面先来说下平 ...

  3. Java线程池中线程的状态简介

    首先明确一下线程在JVM中的各个状态(JavaCore文件中) 1.死锁,Deadlock(重点关注) 2.执行中,Runnable(重点关注) 3.等待资源,Waiting on condition ...

  4. U盘安装centos7 系统卡在 starting dracut initqueue hook

    U盘安装centos7启动过程中出现: [ok] Reached target Basic System 或者 [ok] starting dracut initqueue hook 下面是我解决的过 ...

  5. ASP.NET购物车Cookie获取,创建,添加,更新,删除的用法

    #region 添加购物车 public void GetShoppingCart(int skuId, int quanlity) { HttpCookie cookie = HttpContext ...

  6. 安装Fedora后

    更新操作系统版本: https://fedoraproject.org/wiki/DNF_system_upgrade    靠谱: 设置ssh:ssh生成公钥私钥.默认root(.ssh/confi ...

  7. Charles 笔记

    一. Charles工作原理 本质就是一个http抓包分析工具,在工作的时候将charles设置成代理服务器,所有网络请求都会经过Charles,这样就实现了网络封包的截取和分析. 主要功能 截取ht ...

  8. PowerMock学习(五)之Verifying的使用

    前言 Verifying是一个非常强大的测试工具,在mock系列框架中使用广泛,主要用于验证方法是否被调用,下面将举例说明. 场景 模拟这样一个场景,通过Dao查询学生,如果存在更新原来学生,不存在则 ...

  9. 微信小程序 + thinkjs + mongoDB 实现简单的前后端交互

    说明:这段时间跟老师学习了一下mongodb数据库,这次也是第一次搭建后台服务,出了不少差错,特此来复盘一下,非常感谢对我提供帮助的同学~ 一.使用 thinkjs + mongodb 创建后台服务 ...

  10. 前端开发单位em

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...