[hdu 4416]Good Article Good sentence
最近几天一直在做有关后缀自动机的题目
感觉似乎对后缀自动机越来越了解了呢!喵~
这题还是让我受益颇多的,首先搞一个后缀自动机是妥妥的了
可是搞完之后呢?
我们来观察 step 这个变量,每个节点的 step 是从根节点到此节点所经过的最长步数
那么也就是以该点为结尾的最长的后缀长度
如何统计不被 Bi 串包含的子串呢?
其实很简单,维护每个节点所能匹配的最长的字符串长度
然后 节点->step-max(该节点所能匹配的最长的字符串长度, 节点->fail->step) 就是答案了
因为 S[0..节点->step-1] 必是原串的一个后缀,而 节点所能匹配的最长字符串长度 d 说明 S[节点->step-d..节点->step-1] 是出现在了某个 Bi 串中的
只不过把每个串在自动机上跑一遍并不能得到每个节点所能匹配的最长长度
因为当该节点被匹配时,该结点的 fail 指针所指向的节点也必然被匹配到了
我们需要一个拓扑排序,按拓扑序来更新答案,并同时更新每个节点的 fail 指针指向的点的匹配长度
教练,我不想写拓扑排序~
我才不会说按 step 从大到小的顺序就是拓扑序呢喵~
namespace 写写被 hdu 怒骂 TLE TAT ,这是多么痛的领悟……
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ord(ch) ((ch)-'a')
typedef long long llint;
const int sizeOfString=;
const int sizeOfMemory=<<;
const int sizeOfType=; inline int max(int x, int y) {return x>y?x:y;} struct node
{
int step;
int same;
node * fail;
node * ch[sizeOfType];
};
node memory[sizeOfMemory]; int port;
node * dfa=memory, * last;
inline node * newnode(node * t=NULL)
{
node * newt=memory+(port++);
newt->step=;
newt->same=;
if (t) newt->fail=t->fail, t->fail=newt, memcpy(newt->ch, t->ch, sizeof t->ch);
else newt->fail=NULL, memset(newt->ch, , sizeof newt->ch);
return newt;
}
inline void insert(int w)
{
node * p=last, * newp=newnode();
newp->step=p->step+; for ( ;p->ch[w]==NULL;p=p->fail) p->ch[w]=newp;
if (p->ch[w]==newp)
newp->fail=dfa;
else
{
node * q=p->ch[w];
if (q->step==p->step+)
newp->fail=q;
else
{
node * newq=newnode(q);
newq->step=p->step+;
newp->fail=newq;
for ( ;p->ch[w]==q;p=p->fail) p->ch[w]=newq;
}
} last=newp;
}
inline void search(char * s)
{
int len=strlen(s);
int tot=;
node * t=dfa;
for (int i=;i<len;i++)
{
int w=ord(s[i]);
if (t->ch[w])
{
t=t->ch[w];
t->same=max(t->same, ++tot);
}
else
{
node * j;
for (j=t->fail;j!=dfa && !j->ch[w];j=j->fail);
if (j->ch[w])
{
t=j->ch[w];
t->same=max(t->same, tot=(j->step+));
}
else
{
t=dfa;
tot=;
}
}
}
}
inline llint calc(int len)
{
static node * p[sizeOfMemory];
static int cnt[sizeOfString];
llint ret=; memset(cnt, , sizeof(cnt));
for (int i=;i<port;i++) cnt[dfa[i].step]++;
for (int i=;i<=len;i++) cnt[i]+=cnt[i-];
for (int i=;i<port;i++) p[--cnt[dfa[i].step]]=&dfa[i];
for (int i=port-;i>;i--)
{
p[i]->fail->same=max(p[i]->fail->same, p[i]->same);
if (p[i]->same<p[i]->step)
ret+=p[i]->step-max(p[i]->same, p[i]->fail->step);
} return ret;
} int T, n;
char str[sizeOfString], s[sizeOfString]; int main()
{
int cases=; for (scanf("%d", &T);T;T--)
{
scanf("%d", &n);
scanf("%s", str);
port=; dfa=newnode(); dfa->fail=dfa; last=dfa;
int len=strlen(str);
for (int i=;i<len;i++)
insert(ord(str[i]));
for (int i=;i<=n;i++)
{
scanf("%s", s);
search(s);
}
printf("Case %d: %I64d\n", ++cases, calc(len));
} return ;
}
本傻装B不成反被艹系列
[hdu 4416]Good Article Good sentence的更多相关文章
- HDU 4416 Good Article Good sentence(后缀自动机)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4416 [题目大意] 给出一个字符串,然后,给出一个字符串集合,问在该字符串中出现,且不在字符串集合 ...
- HDOJ 4416 Good Article Good sentence
题解转自:http://blog.csdn.net/dyx404514/article/details/8807440 2012杭州网络赛的一道题,后缀数组后缀自己主动机都行吧. 题目大意:给一个字符 ...
- HDU 4416 (后缀自动机)
HDU 4416 Good Article Good sentence Problem : 给一个串S,和一些串T,询问S中有多少个子串没有在T中出现. Solution :首先对所有的T串建立后缀自 ...
- Good Article Good sentence HDU - 4416 (后缀数组)
Good Article Good sentence \[ Time Limit: 3000 ms\quad Memory Limit: 32768 kB \] 题意 给出一个 \(S\) 串,在给出 ...
- Good Article Good sentence HDU - 4416 (后缀自动机)
Good Article Good sentence \[ Time Limit: 3000 ms\quad Memory Limit: 32768 kB \] 题意 给出一个 \(S\) 串,在给出 ...
- hdu 3507 Print Article(斜率优化DP)
题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...
- HDU 3507 - Print Article - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 Zero has an old printer that doesn't work well s ...
- HDU 3507 Print Article 斜率优化
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3507 Print Article(DP+斜率优化)
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
随机推荐
- gsoap框架下的onvif程序流程分析
SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap) { do { unsigned int k = soap->max_keep_al ...
- C# IList<T>转为DataTable
public class WebUtil { /// <summary> /// 转换IList<T>为DataTable/// </summary> /// &l ...
- JVM-JDK命令行工具
JDK命令行工具 当我们进入JDK的安装目录里面的/bin目录,会发现有很多小工具,有我们熟悉的也经常用的java,javac,也有很多我们不怎么用到很陌生的工具.下面看看哪些平时不怎么用到的工具吧. ...
- 转:gartner 2014-07 ETL工具象限排名
ref: http://www.gartner.com/technology/reprints.do?id=1-1YAXV15&ct=140728&st=sb
- 详解模块定义(.def)文件
一个完整的Windows应用程序(C++程序)通常由五种类型的文件组成:源程序文件,头文件,资源描述文件,项目文件,模块定义文件.本文主要讲解模块定义文件. 模块定义 (.def)文件为链接器提供有关 ...
- PHP使用mysqli操作MySQL数据库
PHP的 mysqli 扩展提供了其先行版本的所有功能,此外,由于 MySQL 已经是一个 具有完整特性的数据库服务器 , 这为PHP 又添加了一些新特性 . 而 mysqli 恰恰也支持了 这些新特 ...
- ASP开发中服务器控件和普通控件的区别
1.对于服务器按钮控件(即<asp:Button>类型的按钮):服务器响应事件:OnClick客户端响应属性:OnClientClick 2.对于html按钮控件(即<input t ...
- parse,tryparse区别
Convert.ToInt32.int.Parse(Int32.Parse).int.TryParse.(int) 四者都可以解释为将类型转换为 int,那它们的区别是什么呢? Convert.ToI ...
- 转--->svn的使用
在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境.在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还 ...
- re-id 资料集
Shengcai Liao: http://www.cbsr.ia.ac.cn/users/scliao/