最近几天一直在做有关后缀自动机的题目

感觉似乎对后缀自动机越来越了解了呢!喵~

这题还是让我受益颇多的,首先搞一个后缀自动机是妥妥的了

可是搞完之后呢?

我们来观察 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的更多相关文章

  1. HDU 4416 Good Article Good sentence(后缀自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4416 [题目大意] 给出一个字符串,然后,给出一个字符串集合,问在该字符串中出现,且不在字符串集合 ...

  2. HDOJ 4416 Good Article Good sentence

    题解转自:http://blog.csdn.net/dyx404514/article/details/8807440 2012杭州网络赛的一道题,后缀数组后缀自己主动机都行吧. 题目大意:给一个字符 ...

  3. HDU 4416 (后缀自动机)

    HDU 4416 Good Article Good sentence Problem : 给一个串S,和一些串T,询问S中有多少个子串没有在T中出现. Solution :首先对所有的T串建立后缀自 ...

  4. Good Article Good sentence HDU - 4416 (后缀数组)

    Good Article Good sentence \[ Time Limit: 3000 ms\quad Memory Limit: 32768 kB \] 题意 给出一个 \(S\) 串,在给出 ...

  5. Good Article Good sentence HDU - 4416 (后缀自动机)

    Good Article Good sentence \[ Time Limit: 3000 ms\quad Memory Limit: 32768 kB \] 题意 给出一个 \(S\) 串,在给出 ...

  6. hdu 3507 Print Article(斜率优化DP)

    题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...

  7. 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 ...

  8. HDU 3507 Print Article 斜率优化

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  9. HDU 3507 Print Article(DP+斜率优化)

     Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) ...

随机推荐

  1. [C/C++]C/C++相关网站

    1.http://en.cppreference.com What is the purpose of this site? Our goal is to provide programmers wi ...

  2. PDF2SWF转换只有一页的PDF文档,在FlexPaper不显示解决方法

    问题:PDF2SWF转换只有一页的PDF文档,在FlexPaper不显示! FlexPaper 与 PDF2SWF 结合是解决在线阅读PDF格式文件的问题的,多页的PDF文件转换可以正常显示,只有一页 ...

  3. C#特性

    一.概念:C#的特性也是一个类,继承自System.Attribute,用于描述类.方法.字段等 二.类型:   2.1  .net中特性用来处理多种问题,比如序列化.程序的安全特性.防止即时编译器对 ...

  4. Sublime Text2 jedi插件离线安装

    1.Sublime Text2 下载安装 2.下载jedi    gitbub上的,https://github.com/srusskih/SublimeJEDI 3.打开sublime后,组合键“c ...

  5. LNA和PA

    低噪声放大器(Low Noise Amplifier) -------------LNA 功率放大器(Power Amplifier)---------------------PA LNA是低噪声放大 ...

  6. Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

    Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK fla ...

  7. C/C++ memmove 和 memcpy

    这两个函数用于拷贝字符串或者一段连续的内存,函数原型: void * memcpy ( void * destination, const void * source, size_t num ); v ...

  8. swift简介

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

  9. Python的文件类型

    Python的文件类型主要分为3种:源代码(source file).字节码(byte-code file).优化的字节码(optimized file).这些代码都可以直接运行,不需要编译或者连接. ...

  10. Windows 2008 R2防火墙,允许被ping

    netsh firewall set icmpsetting 8 1.         准备 1)         原因 出于安全因素考虑,在Windows 2008 R2上是不允许从外部对其Ping ...