题目链接:HDU-5129

题目大意为给一堆字符串,问由任意两个字符串的前缀子串(注意断句)能组成多少种不同的字符串。

思路是先用总方案数减去重复的方案数。

考虑对于一个字符串S,如图,假设S1,S2,S3,S4,S5,S6均为前缀。

换言之,对于这种字符串,我们计算了三次。

发现,重复的方案数,等于中间如图有颜色的方块的数量。所以我们要做的也就是计数像图中有颜色的小方块的数量。

我们可以通过遍历像S6一样的字符串的数量,来计算重复的方案数。S6满足以下条件:

  1. 存在一个前缀S4为S6的后缀,且S4为S6的最长的“是前缀的”后缀(保证是小方块间没有隔板)。
  2. S6-S4为某个前缀的后缀(在图中为S3的后缀)。

我们发现,对于某一个S6,其对应的S4时一定的。

我们用sum[S]表示以S为后缀的前缀字符串的数量。

这样,当我们遍历S6,对于每一个S6,我们找到其对应的S4后,只要减去( sum[S6-S4] - 1 )即可。

所以我们要处理的,就是以下两个问题:

  1. 如何找到S6对应的S4
  2. 如何求sum[S]

这时候,我们发现S6与S4的关系,和AC自动机的性质很像。S6在失配时跳到的位置就是S4。于是第一个问题解决了。

对于第二个问题,我们同样可以通过AC自动机找到。具体的参见代码。

 #include<cstring>
#include<cstdio>
#include<queue>
using namespace std; typedef long long LL;
const LL MAXN=;
const LL SIGMA_SIZE=;
struct Trie
{
LL ch[MAXN][SIGMA_SIZE];
LL fa[MAXN];
LL sz; //节点总数
Trie() { sz=; fa[]=-; memset(ch[],,sizeof(ch[])); }
LL idx(char c) { return c-'a'; } //节点c的编号
void clear() { sz=; fa[]=-; memset(ch[],,sizeof(ch[])); } //在Trie中插入字符串s
void insert(char *s)
{
LL u=,n=strlen(s);
for(LL i=;i<n;i++)
{
LL c=idx(s[i]);
if(!ch[u][c]) //节点不存在
{
memset(ch[sz],,sizeof(ch[sz]));
fa[sz]=u;
ch[u][c]=sz++; //新建节点
}
u=ch[u][c]; //往下走
}
} //AC自动机部分
LL f[MAXN];
LL deg[MAXN];
LL sum[MAXN]; //sum[i]表示以Si为后缀的前缀的数量
void getFail()
{
queue<LL> q;
f[]=;
//初始化队列
for(LL c=;c<SIGMA_SIZE;c++)
{
LL u=ch[][c];
if(u) { f[u]=; q.push(u); }
}
//按BFS顺序计算失配函数
while(!q.empty())
{
LL r=q.front(); q.pop();
for(LL c=;c<SIGMA_SIZE;c++)
{
LL u=ch[r][c];
if(!u) { ch[r][c]=ch[f[r]][c]; continue; }
q.push(u);
LL v=f[r];
f[u]=ch[v][c];
}
}
for(LL i=;i<sz;i++) { deg[i]=; sum[i]=; }
for(LL i=;i<sz;i++) deg[f[i]]++;
queue<LL> Q;
for(LL i=;i<sz;i++) if(!deg[i]) Q.push(i);
while(!Q.empty())
{
LL u=Q.front(); Q.pop();
sum[f[u]]+=sum[u];
deg[f[u]]--;
if(!deg[f[u]]) Q.push(f[u]);
}
} void solve()
{
LL tot=;
for(LL i=;i<sz;i++) if(f[i])
{
LL j=f[i];
LL p=i;
while(j)
{
p=fa[p];
j=fa[j];
}
tot+=sum[p]-;
}
printf("%lld\n",1LL*(sz-)*(sz-)-tot);
}
};
Trie T;
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
LL n;
while(scanf("%lld",&n) && n)
{
scanf("%lld",&n);
for(LL i=;i<=n;i++)
{
char s[];
scanf("%s",s);
T.insert(s);
}
T.getFail();
T.solve();
T.clear();
}
return ;
}

HDU 5129 Yong Zheng's Death的更多相关文章

  1. 字符串(AC自动机):HDU 5129 Yong Zheng's Death

    Yong Zheng's Death Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/O ...

  2. hdu 5129 (枚举) The E-pang Palace

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5128. 给你n个点,问能否组成两个不相交的与坐标轴平行的矩形,能就输出两矩形的面积和,不能就输出一个字符串 ...

  3. 2014ACM/ICPC亚洲区广州站题解

    这一场各种计算几何,统统没有做. HDU 5129 Yong Zheng's Death HDU 5136 Yue Fei's Battle

  4. 推荐系统(1)--splitting approaches for context-aware recommendation

    开篇语: 大一的时候.在实验室老师和师兄的带领下.我開始接触推荐系统.时光匆匆,转眼已是大三,因为大三课甚是少.于是便有了时间将自己所学的东西做下总结. 第一篇博客.献给过去三年里带我飞的老师和师兄们 ...

  5. HDU 5860 Death Sequence(死亡序列)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  6. HDU 5860 Death Sequence(递推)

    HDU 5860 Death Sequence(递推) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 Description You ...

  7. HDU 6136 Death Podracing(循环链表)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6136 [题目大意] 一堆人在操场上跑步,他们都有一定的速度和初始位置, 当两个人相遇的时候编号较小 ...

  8. 2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后 ...

  9. HDU 6136 Death Podracing (堆)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6136 题解 完了,普及题都不会做了... 发现一个重要性质是只有相邻的人才会相撞,于是直接拿堆维护即可 ...

随机推荐

  1. 【bzoj5049】[Lydsy九月月赛]导航系统 并查集+双向BFS最短路

    题目描述 给你一张 $n$ 个点 $m$ 条边的随机图,边权为1.$k$ 次询问两点间最短路,不连通则输出-1. 输入 第一行包含3个正整数n,m,k(2<=n<=100000,1< ...

  2. Python 嵌套函数和闭包

    Python 嵌套函数和闭包 1.函数嵌套 如果在一个函数内部定义了另一个函数,我们称外部的函数为外函数,内部的函数为内函数,如下代码: def out_func(): def inner_func1 ...

  3. python 内存分析

    1.改源码重新编译打印相关信息 obmalloc.c 文件中打印 maxarenas,值为当前环境分配 arena 个数:分配 arena 时并没有马上分配对应的pools,故对于每一个 arena, ...

  4. python中深copy,浅copy

    版权声明:本文为博主原创文章,未经博主允许不得转载. >>> mylist1 = [1, 2, 3, 4] >>> myl = mylist1 >>&g ...

  5. 【题解】APIO2018 Duathlon 铁人两项

    首先对于给出的图建立圆方树,然后我们分类讨论每一个点作为中间的中转站出现的情况有多少种,累积到 \(ans\) 中. 对于圆点:在任意两个子树内分别选出一个节点都是合法的. 对于方点:连接向方点的点均 ...

  6. CentOS 装hadoop3.0.3 版本踩坑

    1.but there is no HDFS_NAMENODE_USER defined. Aborting operation. [root@xcff sbin]# ./start-dfs.sh S ...

  7. 如何使用Navicat连接Oracle

    1.Navicat连接Oracle,需要使用OCI库.因此先要安装Oracle提供的客户端instantclient-basic, 请注意,32位的Navicat需要下载配置32位的instantcl ...

  8. 【题解】Huge Mods UVa 10692 欧拉定理

    题意:计算a1^( a2^( a3^( a4^( a5^(...) ) ) ) ) % m的值,输入a数组和m,不保证m是质数,不保证互质 裸的欧拉定理题目,考的就一个公式 a^b = a^( b % ...

  9. uva 11424

    uva 11424 GCD - Extreme (I) 题意:思路:(见http://www.cnblogs.com/Duahanlang/p/3184994.html ) 差别在于数据规模和时间,其 ...

  10. js的数据类型--数字

    近期做一些项目的时候发现,自己的js基础还是不够扎实,再看一遍犀牛书,加深自己的理解和印象.所以从这篇文章开始,后面都是关于原生js的一些内容. 这篇文章,我们具体介绍一下js的数据类型其中一种. j ...