传送门
【题目分析】
其实方法还是很好想的,肯定是将所有的单词丢进一棵Trie树里进行操作。
所以关键是如何对文本进行查询。
我们直接深搜,对每个位置查找下一位是否可以接上,如果扫完了一个单词,那么直接枚举从这个位置断开的方案。
当然如果接不上直接break掉就行了,记得每次都要更新ans。
对于一个地方,如果已经搜过了那么没必要再搜一次因为可以接上的最大长度不会改变。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e6+10;
int n,q,ans;
char s[MAXN];
int vis[MAXN];
int cnt;
struct Trie{
int son[26];
int val;
}tr[1000];
void insert(){
int now=0;
int len=strlen(s);
for(int i=0;i<len;++i){
if(!tr[now].son[s[i]-'a']){
tr[now].son[s[i]-'a']=++cnt;
}
now=tr[now].son[s[i]-'a'];
}
tr[now].val++;
}
void dfs(int pos,int len){
if(vis[pos])
return ;
vis[pos]=1;
int now=0;
if(pos>ans)
ans=pos;
int x=pos;
while(x<len){
if(tr[now].son[s[x]-'a']){
now=tr[now].son[s[x]-'a'];
x++;
if(tr[now].val)
dfs(x,len);
}
else
break;
}
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i){
scanf("%s",s);
insert();
}
for(int i=1;i<=q;++i){
memset(vis,0,sizeof(vis));
ans=0;
scanf("%s",s);
dfs(0,strlen(s));
cout<<ans<<'\n';
}
return 0;
}