题解
- dp[i]表示表示前缀i能否匹配,那么转移方程显然是dp[i]=dp[j]&&(j-i能否匹配) (j<=i)
- 走的方向是唯一的,那么显然可以用Trie树来维护.
- 但是还有一个问题,我们是往前匹配,然而正常的Trie树上反向走并不好走,解决方法是反向建Trie树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using namespace std;
const int N=1e6+7;
int tr[N][26],end[N],dp[N],cnt,n,m;
char a[N];
inline void add(char *str){
int len=strlen(str)-1,p=0;
repd(i,len,0){
int k=str[i]-'a';
if(!tr[p][k])tr[p][k]=++cnt;
p=tr[p][k];
}
end[p]++;
}
inline void query(char *str,int pos){
int p=0,flag=0;
repd(i,pos-1,0){
if(!tr[p][str[i]-'a'])break;
p=tr[p][str[i]-'a'];if(dp[i]&&end[p])flag=1;
}
dp[pos]=flag;
}
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n){scanf("%s",a);add(a);}
rep(i,1,m){
int ans=0;
scanf("%s",a);
memset(dp,0,sizeof(dp));
int len=strlen(a);
dp[0]=1;
rep(i,1,len){query(a,i);if(dp[i])ans=max(i,ans);}
printf("%d\n",ans);
}
return 0;
}