这个题目就是AC自动机的一个半板子题,难度不大(然而似乎没什么人用AC自动机)
似乎暴力跑的更快???(应该只是我水)
直接建AC自动机,然后跑就信了(喵喵喵???)
用广搜的样式(懒得慌STL好),DP的思想,然后就那样的找,最后能跑到的最后面的一个就是我们要找的长度(因为如果前面的有问题他是泡不到后面的,正确性一定可以保证)
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=5010000;
int ch[N][26],fail[N],n,m,tot,vis[N],dep[N];
void insert(string s) {
int l=s.size(),x,u=0;
for(int i=0; i<l; ++i) {
x=s[i]-'a';
if(!ch[u][x]) ch[u][x]=++tot,dep[ch[u][x]]=dep[u]+1;
u=ch[u][x];
}
vis[u]=1;
}
void get_fail() {
queue <int> q;
for(int i=0; i<26; ++i)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0; i<26; ++i) {
if(ch[u][i]) {
fail[ch[u][i]]=ch[fail[u]][i];
q.push(ch[u][i]);
} else
ch[u][i]=ch[fail[u]][i];
}
}
}
int book[N];
int search(string s) {
int u=0,l=s.size(),sum=0;
book[0]=1;
for(int i=0; i<l; ++i) {
int x=s[i]-'a';
u=ch[u][x];
for(int j=u; j; j=fail[j]) {
if(vis[j]&&book[i-dep[j]+1]) {
book[i+1]=1;
break;
}
}
}
for(int i=l; i; --i) if(book[i]) return i;
return 0;
}
int main() {
cin>>n>>m;
for(int i=1; i<=n; ++i) {
string ss;
cin>>ss;
insert(ss);
}
get_fail();
for(int i=1; i<=m; ++i) {
string s;
cin>>s;
cout<<search(s)<<endl;
int l=s.size();
for(int i=1; i<=l; ++i) book[i]=0;
}
return 0;
}