题目描述
给出一个字典和一个句子,求最多能理解到这句话的第几个位置(前缀)。
思路
字典树,自然如同它的名字一样,可以用来处理字典的问题。首先显然我们可以建一棵字典树,接下来我们明确我们求的是能理解的前缀,而不是总长度,因此不是多字符串匹配,不用AC自动机。由于字典中的单词可能会有嵌套,我们考虑用f[i]表示我们是否可以匹配到这一位,所以我们可以从每一位可以匹配的地方出发,进行字符串匹配,再记录答案。而最大的i满足f[i]=1就是答案。
代码
#include <bits/stdc++.h> using namespace std; int ch[1000005][30],tot; char s[30],ss[1000005]; bool ed[1000005],f[1000005]; void insert(char *s) { int u=1,len=strlen(s); for(int i=0;i<len;i++) { int c=s[i]-'a'; if(!ch[u][c])ch[u][c]=++tot; u=ch[u][c]; } ed[u]=1; } int find(char *s) { int u=1,len=strlen(s+1); int ans=0; memset(f,0,sizeof(f)); f[0]=1; for(int i=0;i<=len;i++) { if(!f[i])continue ; else ans=i; u=1; for(int j=i+1;j<=len;j++) { // cout<<j<<' '<<s[j]<<endl; int c=s[j]-'a'; if(!ch[u][c])break ; u=ch[u][c]; if(ed[u])f[j]=1; } } return ans; } int main() { int n,m; scanf("%d%d",&n,&m); tot=1; for(int i=1;i<=n;i++) { scanf(" %s",s); insert(s); } for(int i=1;i<=m;i++) { scanf(" %s",ss+1); printf("%d\n",find(ss)); } return 0; }