http://www.lydsy.com/JudgeOnline/problem.php?id=1212
建好AC自动机在Trie树上进行DP
dp[i]|=dp[i-tr[tmp].len]
找到dp[1]==1的max{i}
#include<cstdio>
#include<queue>
#include<cstring>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
#define ROF(i,s,t) for(register int i=s;i>=t;--i)
const int N=1000011;
std::queue<int>q;
int dp[N];
namespace AC_automaton{
char s[N];
char A[N];
struct Tire{
int fail;
int to[26];
int len;
}tr[N];
int tot;
inline void insert(char *s,int pos){
int u=0,v;
for(register int i=1;s[i]!='\0';++i){
if(!tr[u].to[s[i]-'a'])
tr[u].to[s[i]-'a']=++tot;
u=tr[u].to[s[i]-'a'];
}
tr[u].len=strlen(s+1);
}
inline void build_fail(){
int u,v,now;
FOR(i,0,25)
if((u=tr[0].to[i])){
tr[u].fail=0;
q.push(u);
}
while(!q.empty()){
now=q.front();q.pop();
FOR(i,0,25){
v=tr[now].to[i];
u=tr[now].fail;
if(v){
tr[v].fail=tr[u].to[i];
q.push(v);
}
else
tr[now].to[i]=tr[u].to[i];
}
}
}
inline int match(char *s){
int now=0,tmp,n=strlen(s+1);
FOR(i,1,n)dp[i]=0;
dp[0]=1;
int ans=0;
for(register int i=1;i<=n;++i){
now=tr[now].to[s[i]-'a'];
tmp=now;
while(tmp){
dp[i]|=dp[i-tr[tmp].len];
tmp=tr[tmp].fail;
if(dp[i]){ans=i;break;}
}
}
return ans;
}
}
using namespace AC_automaton;
int n,m;
int main(){
scanf("%d%d",&n,&m);
FOR(i,1,n){
scanf("%s",s+1);
insert(s,i);
}
build_fail();
while(m--){
scanf("%s",A+1);
printf("%d\n",match(A));
}
return 0;
}