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

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

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

可是搞完之后呢?

我们来观察 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. MongoDB C#驱动中Query几个方法 (转)

    Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...

  2. UIWebView的缓存策略,清除cookie

    缓存策略 NSURLRequestCachePolicy NSURLRequestUseProtocolCachePolicy缓存策略定义在 web 协议实现中,用于请求特定的URL.是默认的URL缓 ...

  3. php大力力 [009节]php在百度文库的几个基础教程

    2015-08-23 php大力力009. php在百度文库的几个基础教程 php大力力 [009节]php在百度文库的几个基础教程 PHP脚本中操作MySQL数据库3-猿代码平台 php基础教程-绝 ...

  4. How many instances created in the WebContainer

    When the Servlet container starts, it: reads web.xml; finds the declared Servlets in the classpath; ...

  5. JS手机定位地理位置

    /** * 以下为html5代码,获取地理位置 */ /** * 设置地址 */ function setAddress(json) { var position = document.getElem ...

  6. PHP 防范xss攻击

    XSS 全称为 Cross Site Scripting,用户在表单中有意或无意输入一些恶意字符,从而破坏页面的表现! 看看常见的恶意字符XSS 输入: 1.XSS 输入通常包含 JavaScript ...

  7. HDU 5050

    http://acm.hdu.edu.cn/showproblem.php?pid=5050 大数gcd import java.io.* ; import java.math.* ; import ...

  8. asp.net页面间传值的几种方法

    表单提交 传送页面代码 <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server ...

  9. 第三个Sprint完结工作 用场景来规划测试工作.

    一.根据用户使用场景测试: 1.流程 典型群体 群体 张小明 年龄 7-12岁 职业 小学生 收入 压岁钱还有零花钱 能力 看一些简单的数,做一些相对简单的事 爱好 玩游戏 典型场景 张小明平时喜欢玩 ...

  10. 实例讲解Oracle数据库设置默认表空间问题

    实例讲解Oracle数据库设置默认表空间问题   实例讲解Oracle数据库设置默认表空间问题,阅读实例讲解Oracle数据库设置默认表空间问题,DBA们经常会遇到一个这样令人头疼的问题:不知道谁在O ...