P2292 [HNOI2004]L语言
题意:给出n模式串,再给出m个查询串
问:每一个查询串从左到右最多有多少个字符被查到;
思路:将模式串先放进字典树中,然后开始跑查询串
查询串从左到右跑一遍,只要可以从这个位置开始跑,就跑
那怎样才能从这个位置开始跑呢,就是在这之前得所有字符都满足了被查询到
但是:这样子得话复杂度最差会达到1e8 10x20x1024x1024=2e8
所以代码超时了,可是参考别人博客的时候,发现别人的代码跟我写的差不多,不过不超时
找了许久都找不出差别。。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
这是别人不用吸氧还能ac的代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }