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

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

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

可是搞完之后呢?

我们来观察 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. jQuery 元素遍历

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. IIS 发布后文件拒绝访问

    今天遇到一个很小的问题,代码中写XML文件,本地运行没有问题,一发布到服务器上就出现 代码如下: XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load ...

  3. catch的执行与try的匹配

    这里有一段代码: public class EmbededFinally { public static void main(String args[]) { int result; try { Sy ...

  4. (转)Eclipse “cannot be resolved to a type” error

    原:http://www.cnblogs.com/xuxm2007/archive/2011/10/20/2219104.html Eclipse “cannot be resolved to a t ...

  5. Planning for a period of time

    After a period of struggle , i decided to follow the teacher Chen learning . Say true i really disli ...

  6. Executing modules as scripts

    When you run a Python module with python fibo.py <arguments> the code in the module will be ex ...

  7. Shell’s Sort

    Solution 1 : (数据结构与算法分析 C++描述 第三版) template<class T> void shellSort(vector<T> &v) { ...

  8. Java 集合深入理解(5):AbstractCollection

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天好累,来学学 AbstractCollection 吧! 什么是 AbstractCollection Abstrac ...

  9. Android屏幕底部弹出DialogFragment(3)

     Android屏幕底部弹出DialogFragment(3) 附录文章1,2的DialogFragment是常规的DialogFragment,但是现在的一些Android开发中,往往需要从底部 ...

  10. this的指向及应用

    this的指向: //this 指的是调用 当前方法 (函数) 的那个对象 function fn1(){ this; } //fn1(); this => window //obj.oncli ...