Problem Description
In middle school, teachers used to encourage us to pick up pretty sentences so that we could apply those sentences in our own articles. One of my classmates ZengXiao Xian, wanted to get sentences which are different from that of others, because he thought the distinct pretty sentences might benefit him a lot to get a high score in his article.
Assume that all of the sentences came from some articles. ZengXiao Xian intended to pick from Article A. The number of his classmates is n. The i-th classmate picked from Article Bi. Now ZengXiao Xian wants to know how many different sentences she could pick from Article A which don't belong to either of her classmates?Article. To simplify the problem, ZengXiao Xian wants to know how many different strings, which is the substring of string A, but is not substring of either of string Bi. Of course, you will help him, won't you?
 
Input
The first line contains an integer T, the number of test data. 
For each test data
The first line contains an integer meaning the number of classmates.
The second line is the string A;The next n lines,the ith line input string Bi.
The length of the string A does not exceed 100,000 characters , The sum of total length of all strings Bi does not exceed 100,000, and assume all string consist only lowercase characters 'a' to 'z'.
 
Output
For each case, print the case number and the number of substrings that ZengXiao Xian can find.
 
Sample Input
3
2
abab
ab
ba
1
aaa
bbb
2
aaaa
aa
aaa
 
Sample Output
Case 1: 3
Case 2: 3
Case 3: 1
 

T中的字符串依次拿去和S的自动机匹配。每次匹配到一个状态,更新这个状态所匹配的最大的长度p,那么这个状态所表示的子串中长度大于p的即为我们要找的。在计算答案的时候,我们还要同时更新目前状态的pre状态的p值,所以要按逆拓扑序计算总答案。

 

个人照hihocoder的代码写了几条,发现hihocoder的SAM代码的确没有别人的优美啊,所以我决定用别人的风格:

觉得这种代码好的理由:

【结构体】:

          1,在写矩阵的时候我习惯把函数写在结构体里,感觉是要方便些。

                2,根据不同的题有不同的改变,在结构体里做点改变不容易搞混而出错。

                3,事实证明结构体里面的函数运行快一些(我也记不得在哪里看过这个说法了)

【膜拜作者】:

第一次看到Max这样写,很six。

处理的时候:

             1,匹配部分和hiho1465是一样的道理。

             2,拓扑没有用前面hihocoder的题一样利用入度ind用队列来做,而是用基数排序来得到拓扑序列,殊途同归,但是代码简洁一些。

             3,注意start到底是1还是0,各自有不同的临界条件。

感受:多写几遍自动机,感觉还是有点入门了,233......后缀数组失宠了,回头再结合后缀数组分析一遍这些题。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
typedef long long ll;
void Min(ll &a,ll b) { if(a>b) a=b; }
void Max(ll &a,ll b) { if(a<b) a=b; }
const int maxn=1e5+;
const int Sigma=;
char S[maxn];
struct SAM{
int len[maxn<<],fa[maxn<<];//len是maxlen;fa是slink;next是trans;
int next[maxn<<][Sigma];
int cnt[maxn<<],b[maxn<<];
ll dp[maxn<<];
int sz,last;
void init(){//start from 1
sz=last=;
len[]=fa[]=;
memset(next[],,sizeof(next[]));
}
void add(int x){//np,nq是新产生的状态;p,q是转移用的变量
int p=last,np=++sz;last=np;
len[np]=len[p]+;
memset(next[np],,sizeof(next[np]));
while(p&&!next[p][x]) next[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else {
int q=next[p][x];
if(len[q]==len[p]+) fa[np]=q;
else{
int nq=++sz;
memcpy(next[nq],next[q],sizeof(next[q]));//nq代替q;p继续接受后面的
fa[nq]=fa[q],fa[np]=fa[q]=nq;
len[nq]=len[p]+;
while(p&&next[p][x]==q) next[p][x]=nq,p=fa[p];
}
}
}
void sort(){
memset(cnt,,sizeof(cnt));
for(int i=;i<=sz;i++) ++cnt[len[i]];//基数排序,得到top序列
for(int i=;i<=sz;i++) cnt[i]+=cnt[i-];
for(int i=;i<=sz;i++) b[cnt[len[i]]--]=i;
}
void solve(int n){
memset(dp,,sizeof(dp));
while(n--){
scanf("%s",S);
int q=,l=;//从start开始匹配自动机
for(char *p=S;*p;++p){
int x=*p-'a';
while(q>&&!next[q][x]) q=fa[q],l=len[q];
if(next[q][x]) q=next[q][x],++l;
Max(dp[q],l);
}
}
ll ans=;
for(int i=sz;i>;i--){
Max(dp[fa[b[i]]],dp[b[i]]);//长到短
Min(dp[fa[b[i]]],len[fa[b[i]]]);//长度加以限制
}
for(int i=;i<=sz;i++){
ll minlen=dp[i];
if(fa[i]) Max(minlen,len[fa[i]]);
ans+=len[i]-minlen;
}
printf("%lld\n",ans);
}
};
SAM sam;
int main()
{
int T,Case=;scanf("%d",&T);
while(T--){
sam.init();
int n;
scanf("%d",&n);
scanf("%s",S);
for(char *p=S;*p;++p) sam.add(*p-'a');//字符串的指针,学到了
sam.sort();
printf("Case %d: ",++Case);
sam.solve(n);
}
return ;
}

HDU4416Good Article Good sentence(后缀自动机)的更多相关文章

  1. [hdu4416 Good Article Good sentence]后缀自动机SAM

    题意:给出串A和串集合B={B1,B2,...,Bn},求串A的所有不同子串中不是B中任一串的子串的数目. 思路:把A和B中所有字符串依次拼接在一起,然后构造后缀自动机,计算每个状态的R集合元素的最大 ...

  2. BZOJ 4516: [Sdoi2016]生成魔咒 后缀自动机 性质

    http://www.lydsy.com/JudgeOnline/problem.php?id=4516 http://blog.csdn.net/doyouseeman/article/detail ...

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

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

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

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

  5. HDU 4416 (后缀自动机)

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

  6. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  7. SPOJ NSUBSTR Substrings 后缀自动机

    人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...

  8. hdu4436-str2int(后缀数组 or 后缀自动机)

    题意:给你一堆字符串,仅包含数字'0'到'9'. 例如 101 123 有一个字符串集合S包含输入的N个字符串,和他们的全部字串. 操作字符串很无聊,你决定把它们转化成数字. 你可以把一个字符串转换成 ...

  9. HDOJ 4416 Good Article Good sentence

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

随机推荐

  1. CSS 中z-index全解析(摘自阿里西西)

    z-index全解析 Z-index属性决定了一个HTML元素的层叠级别.元素层叠级别是相对于元素在Z轴上(与X轴Y轴相对照)的位置而言.一个更高的Z-index值意味着这个元素在叠层顺序中会更靠近顶 ...

  2. iOS UIFont 的学习与使用

    通常,我们使用字体 都是系统默认的字体. 有时候 从阅读体验,美观度 设计师都会考虑用一些 更高大尚的字体. 系统字体库 给英文 各种style的发挥空间很大,但是 中文则不然. 但是苹果 给使用中文 ...

  3. VC中添加消息响应函数

    1. 添加消息映射 2. 头文件中添加函数声明 3. 实现文件中添加函数定义

  4. $SVN代码版本管理工具的使用

    SVN是一种代码版本管理工具,具有可视化的操作界面,使用简便,和git的功能类似.下面总结一下SVN的基本用法: 1.安装SVN软件,和安装一般的软件的步骤差不多,这里使用的版本是TortoiseSV ...

  5. python中初始化实例属性

    虽然我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性.例如,Person类应该在创建的时候就拥有 name.gender 和 birth 属性,怎么办? 在 ...

  6. hadoop实战项目:查找相同字母组成的字谜

    前面我们学习了MapReduce编程思想和编程示例,那么本节课程同学们一起操练操练,动手完成下面的项目. 项目需求 一本英文书籍包含成千上万个单词或者短语,现在我们需要在大量的单词中,找出相同字母组成 ...

  7. Python多线程循环

    背景:Python脚本:读取文件中每行,放入列表中:循环读取列表中的每个元素,并做处理操作. 核心:多线程处理单个for循环函数调用 模块:threading 第一部分:   :多线程脚本 (该脚本只 ...

  8. leetcode刷题2:两数相加add_two_numbers

    题目:两数相加 (难度:中等) 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字. 将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以 ...

  9. window.open、window.showModalDialog和window.showModelessDialog 的区别[转]

    一.前言 要打开一个可以载入页面的子窗口有三种方法,分别是window.open.window.showModalDialog和window.showModelessDialog. open方法就是打 ...

  10. Excel下载打不开

    1.问题描述:今天遇到个问题,对于定时发送邮件,前两天还正常,今天发现邮件能收到,但打不开,显示如下错误: 预览邮件显示: 点击Excel打开,显示如下: 2.问题解决方案 删除对于服务器上部分空间内 ...