Link:
Solution:
看到字符串的多模式匹配,正解一般就是Trie树/AC自动机
此题由于每个模式串长度都很小,于是直接在Trie树上暴力就行了
先把所有模式串建一颗Trie树,
用$DP[i]$表示能否匹配到第$i$个字符,如果能,则从第$i+1$位开始继续从根开始匹配,查看能否拓展答案
上述偏暴力的做法复杂度在$O(4*10^8)$左右,
好像还有一种用AC自动机+状压DP的做法能降到$O(10^6)$,后面再填吧
Code:
#include <bits/stdc++.h> using namespace std; const int MAXN=1e6+10; struct trie { int ch[30]; bool flag; }tr[300]; int n,m,dp[MAXN],cnt=1; char s[MAXN]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) //建立Trie树 { scanf("%s",s); int cur=1,len=strlen(s); for(int j=0;j<len;j++) { if(!tr[cur].ch[s[j]-'a']) tr[cur].ch[s[j]-'a']=++cnt; cur=tr[cur].ch[s[j]-'a']; } tr[cur].flag=true; } for(int i=1;i<=m;i++) { scanf("%s",s);memset(dp,0,sizeof(dp)); int len=strlen(s);dp[0]=1; for(int j=0;j<len;j++) { if(!dp[j]) continue; int cur=1,k=j; while(tr[cur].ch[s[k]-'a']) { cur=tr[cur].ch[s[k++]-'a']; if(tr[cur].flag) dp[k]=1; } } for(int j=len;j>=0;j--) if(dp[j]){printf("%d ",j);break;} } return 0; }
Review:
看到多模式匹配,往Trie+AC自动机上想就对了