JZYZOJ1369 [coci2012]覆盖字符串 AC自动机

http://172.20.6.3/Problem_Show.asp?id=1369

trie树如果不优化就这么往里面放这么多单词肯定超空间+超时,所以需要去掉无用的字符串(不属于原字符串的),但是一个一个判断时间又很长;

所以解决方案就是用一个多维vis数组胡搞判定一下,非常魔性。。。

代码

 

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring>  
 4 #include<algorithm>  
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const long long maxn=300010;
 9 const int modn=10000;
10 int n,m;
11 char ch[maxn]={};
12 char ch1[5010]={};
13 int vis[maxn]={};
14 queue<int>q;
15 struct trie{
16     int next[26];
17     bool exist;
18     int fail,d;
19 }e[maxn*4];int tot=0;
20 bool ff[26][26][26][26][26]={};
21 void insert(int k,int d,int x){
22     if(d==k){
23         e[x].exist=1;e[x].d=d;
24         return;
25     }
26     int z=ch1[d]-'a';
27     if(!e[x].next[z])e[x].next[z]=++tot;
28     insert(k,d+1,e[x].next[z]);
29 }
30 void build(){
31     q.push(0);int x,y,f;
32     while(!q.empty()){
33         x=q.front();q.pop();
34         for(int i=0;i<26;i++){
35             y=e[x].next[i];
36             if(y){
37                 if(x!=0){
38                     f=e[x].fail;
39                     while((!e[f].next[i])&&f)f=e[f].fail;
40                     e[y].fail=e[f].next[i];
41                 }q.push(y);
42             }
43         }
44     }
45 }
46 int read(){
47     char chh=getchar();int k=0;
48     while(chh<'a'||chh>'z'){chh=getchar();}
49     while(chh>='a'&&chh<='z'){ch1[k++]=chh;chh=getchar();}
50     return k;
51 }
52 void read1(){
53     char chh=getchar();int k=0;
54     while(chh<'a'||chh>'z'){chh=getchar();}
55     while(chh>='a'&&chh<='z'){ch[k++]=chh;chh=getchar();}
56 }
57 int main(){
58     //freopen("wtf.in","r",stdin);
59     //freopen("wtf.out","w",stdout);
60     scanf("%d",&n);read1();
61     for(int i=4;i<n;i++){
62         ff[(int)ch[i-4]-'a'][(int)ch[i-3]-'a'][(int)ch[i-2]-'a'][(int)ch[i-1]-'a'][(int)ch[i]-'a']=1;
63     }
64     scanf("%d",&m);
65     for(int i=1;i<=m;i++){
66         int siz=read(),wtf=1;
67         for(int j=4;j<siz;j++){
68             if(!ff[(int)ch1[j-4]-'a'][(int)ch1[j-3]-'a'][(int)ch1[j-2]-'a'][(int)ch1[j-1]-'a'][(int)ch1[j]-'a'])
69                 wtf=0;
70         }if(wtf)insert(siz,0,0);
71     }build();
72     int x=0,y;
73     for(int i=0;i<n;i++){
74         int z=ch[i]-'a';
75         while((!e[x].next[z])&&x){
76             x=e[x].fail;
77         }
78         x=e[x].next[z];y=x;
79         while((!e[y].exist)&&y){
80             y=e[y].fail;
81         }vis[i-e[y].d+1]=max(vis[i-e[y].d+1],e[y].d);
82     }
83     int k=0;int t=0;
84     for(int i=0;i<n;i++){
85         k=max(vis[i],k);
86         if(k>0)t++;
87         k--;
88     }
89     printf("%d\n",n-t);
90     return 0;
91 }
View Code

 

转载于:https://www.cnblogs.com/137shoebills/p/7788135.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值