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]!=' ';++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 ",match(A)); } return 0; }