Rt,80pts
p[i]:如 p[i]=16(10000) 则第 i 项到第 i+4−1 是一个单词
dp[i]为从i(下标从0开始)开始可以表示的最大区域(dp[2]=15即从下标为2个单词最远可以理解到第15个单词)
dp[x]=max(i,dp[i+j](p[i] and (1<<j)=1 ))
#include<bits/stdc++.h>
using namespace std;
int n;
char s[30][30],t[2000010];
int trie[30*30*4][30];
int fail[30*30*4];
int ncnt[30*30*4];
int cnt = 0;
int remean[160*100*4];
void inser(int nums){
int id = 0;
int leng = strlen(s[nums]);
for(int i = 0; i < leng; i++){
if(trie[id][s[nums][i]-'a']) id = trie[id][s[nums][i]-'a'];
else {
cnt++;
trie[id][s[nums][i]-'a'] = cnt;
id = cnt;
}
}
ncnt[id]++;
remean[id] = nums;
}
void buildfail(){
queue<int> unq;
fail[0] = 0;
for(int i = 0; i < 26; i++){
if(trie[0][i]){
unq.push(trie[0][i]);
fail[trie[0][i]] = 0;
}
}
while(!unq.empty()){
int fir = unq.front();
unq.pop();
for(int i = 0 ; i < 26; i++){
if(trie[fir][i]){
fail[trie[fir][i]] = trie[fail[fir]][i];
unq.push(trie[fir][i]);
} else {
trie[fir][i] = trie[fail[fir]][i];
}
}
}
}
int p[2000010];
int dp[2000010];
void query(){
int id = 0,leng = strlen(t);
for(int i = 0; i < leng; i++){
id = trie[id][t[i]-'a'];
for(int j = id; j; j = fail[j]){
if(ncnt[j]!=0){
p[i-strlen(s[remean[j]])+1]|=(1<<(strlen(s[remean[j]])));
}
}
}
dp[leng] = leng;
for(int i = leng-1; i >= 0; i--){
dp[i] = i;
for(int j = 1; j <= 20; j++){
if(p[i]&(1<<j)) dp[i] = max(dp[i],dp[i+j]);
}
}
printf("%d\n",dp[0]);
}
int m;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
scanf("%s", s[i]);
inser(i);
}
buildfail();
while(m--){
memset(p,0,sizeof(p));
memset(dp,0,sizeof(dp));
scanf("%s", t);
query();
}
return 0;
}