首页 > 其他 > 详细

190709-sugar-AC自动机/dp

时间:2019-10-13 17:38:50      阅读:96      评论:0      收藏:0      [点我收藏+]
技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 namespace Moxing{
 8     const int N=5e6+50,inf=0x3f3f3f3f;
 9     char b[N],s[N];
10     int c[N][2],fail[N],q[N],mi[N],cnt,l,r,len,a[N],f[N],n;
11     void insert(char *s){
12         int len=strlen(s),now=0;
13         for(int i=0;i<len;i++){
14             int x=s[i]-0;
15             if(!c[now][x]) c[now][x]=++cnt;
16             now=c[now][x];
17         }
18         mi[now]=len;
19     }
20     void build(){
21         for(int i=0;i<2;i++){
22             if(c[0][i]) q[++r]=c[0][i];
23         }
24         l=1;
25         while(l<=r){
26             int x=q[l++];
27             for(int i=0;i<2;i++){
28                 int &y=c[x][i];
29                 if(!y) y=c[fail[x]][i];
30                 else fail[y]=c[fail[x]][i],q[++r]=y,mi[y]=min(mi[y],mi[c[fail[x]][i]]);
31             }
32         }
33     } 
34     void ask(char *s){
35         int now=0;len=strlen(s+1);
36         for(int i=1;i<=len;i++){
37             int x=s[i]-0;
38             now=c[now][x];a[i]=mi[now];
39         } 
40     }
41     struct main{
42         main(){
43             memset(mi,0x3f,sizeof(mi));
44             scanf("%d%s",&n,b+1);
45             for(int i=1;i<=n;i++){
46                 scanf("%s",s),insert(s);
47             }
48             build(),ask(b);
49             for(int i=1;i<=len;i++){
50                 f[i]=f[i-1];
51                 if(a[i]!=inf) f[i]=max(f[i],f[i-a[i]]+1); 
52             }
53             printf("%d",f[len]);
54             exit(0);
55         }
56     }UniversalLove;
57 }
58 int main(){
59     Moxing::main();
60 }
61 //5
62 //010101010111
63 //101
64 //01
65 //11
66 //1000
67 //1110
68 //mi数组记的是now=i时最小的len,a就是串上这个位置作为末尾能匹配到的最短的串的长度
69 //ask函数把now=i时最小的len转换到串的位置上
View Code

技术分享图片

 

以下转自https://www.cnblogs.com/justPassBy/p/5412110.html

fail指针的性质:

每个结点的fail指针都指向自己的最长后缀,让一个结点cur的fail指针不断回溯向上走,直到碰到根结点为止,回溯时经过的结点所代表的字符串都是结点cur所代表的字符串的后缀。

Trie图和AC自动机的区别:

Trie图是AC自动机的确定化形式,即把每个结点不存在字符的next指针都补全了。这样做的好处是使得构造fail指针时不需要next指针为空而需要不断回溯。

比如构造next[cur][i]的fail指针,cur为父节点,next[cur][i]为cur的儿子结点,如果是AC自动机,如果父亲结点tmp(tmp是cur的一份拷贝)的next[fail[tmp]][i]不存在时,需要让tmp不断回溯(即tmp = fail[tmp]),直到next[fail[tmp]][i]不为空时,才让fail[next[cur][i]] = next[fail[tmp]][i]。

如果是Trie图,那么直接让fail[next[cur][i]] = next[fail[cur]][i]就可以了,因为Trie图已经补全了next指针。

fail树:

Fail树其实就是将AC自动机的next指针去掉,然后反转fail指针的指向所构造出来的,而且可以肯定这是一棵树 ,所以称之为Fail树。

Fail树的一个性质是,某个结点所对应的字符串肯定是其儿子结点,孙子结点…所对应的字符串的后缀。

190709-sugar-AC自动机/dp

原文:https://www.cnblogs.com/Moxingtianxia/p/11667011.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!