P2292 [HNOI2004]L语言

题意:给出n模式串,再给出m个查询串
    问:每一个查询串从左到右最多有多少个字符被查到;
思路:将模式串先放进字典树中,然后开始跑查询串
     查询串从左到右跑一遍,只要可以从这个位置开始跑,就跑
        那怎样才能从这个位置开始跑呢,就是在这之前得所有字符都满足了被查询到
    但是:这样子得话复杂度最差会达到1e8    10x20x1024x1024=2e8
    所以代码超时了,可是参考别人博客的时候,发现别人的代码跟我写的差不多,不过不超时
    找了许久都找不出差别。。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e6+10;
 4 int dp[maxn];
 5 char s[100]; char tmp[maxn];
 6 int judge[400];
 7 int trie[400][26]; int tot;
 8 void Insert()
 9 {
10     int rt=0;
11     int len=strlen(s);
12     for(int i=0;i<len;i++){
13         int id=s[i]-'a';
14         if(!trie[rt][id])
15             trie[rt][id]=++tot;
16         rt=trie[rt][id];
17     }
18     judge[rt]=1;
19 }
20 int Search(int x)
21 {
22     int rt=0;
23     int len=strlen(tmp);
24     for(int i=x;i<len;i++){
25         int id=tmp[i]-'a';
26         if(!trie[rt][id]) return 0;
27         rt=trie[rt][id];
28         if(judge[rt]){
29             dp[i]=1;
30         }
31     }  //rt经过此循环后变成前缀最后一个字母所在位置
32 }
33 int main()
34 {
35     int n,m;
36     scanf("%d%d",&n,&m);
37     for(int i=1;i<=n;i++){
38         scanf("%s",s);
39         Insert();
40     }
41     while(m--){
42         scanf("%s",tmp);
43         memset(dp,0,sizeof(dp));
44         int len=strlen(tmp);
45         Search(0);
46         int ans=0;
47         for(int i=0;i<=len-1;i++){
48             if(dp[i]){
49                 ans=max(ans,i+1);
50                 if(i!=len-1)
51                     Search(i+1);
52             }
53         }
54         printf("%d\n",ans);
55     }
56     return 0;
57 }
View Code

这是别人不用吸氧还能ac的代码

 1 #include<iostream>
 2 #include<iomanip>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=20*10+7,maxm=1024*1024+7;
 9 int n,m,rt=1,cnt=1;
10 int t[maxn][26],f[maxm],mark[maxn];char s[maxm];
11 void Insert(int &x,int now,int len)
12 {
13     if(!x) x=++cnt;
14     if(now==len) mark[x]=1;
15     else Insert(t[x][s[now]-'a'],now+1,len);
16 }
17 void my_find(int x,int now,int len)
18 {
19     if(mark[x]&&x) f[now]=1;//还未处理的点是now,现在的位置已经处理过 
20     if(!x||now==len) return ;
21     my_find(t[x][s[now]-'a'],now+1,len);
22 }
23 int main()
24 {
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;++i)
27     {
28         scanf("%s",s);int len=strlen(s);
29         Insert(rt,0,len);
30     }
31     for(int i=1;i<=m;++i)
32     {
33         scanf("%s",s);int len=strlen(s),maxx=0;
34         memset(f,0,sizeof(f));f[0]=1;//表示可以从这个位置开始匹配 
35         for(int j=0;j<=len;++j)
36         if(f[j]) {my_find(rt,j,len);maxx=max(maxx,j);}
37         printf("%d\n",maxx);
38     }
39     return 0;
40 }
View Code

 

posted @ 2020-04-07 16:50  古比  阅读(191)  评论(0编辑  收藏  举报