题意:
给了N个单词,NiuNiu想输入一些字母,想知道在输入这些字母后最少需要多加多少个单词才能使得存在后缀使得与N个单词中的一个匹配。
思路:
把这个N个单词建个AC自动机,在建的过程中每个节点都记录最少要加多少个字母的答案,建个trie图,在跑fail的时候,更新每个节点的答案。最后统计答案的时候模拟一下栈操作就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
char a[maxn];
int ch[maxn][26];
int que[maxn];
int fail[maxn];
int len[maxn];
char s[maxn];
int tot;
int newnode()
{
++tot;
return tot;
}
void ins(char s[])
{
int root=0;
int l=strlen(s);
int i;
for(i=0;s[i];i++)
{
int x=s[i]-'a';
len[root]=min(len[root],l-i);
if(!ch[root][x])
ch[root][x]=newnode();
root=ch[root][x];
}
len[root]=min(len[root],l-i);
}
void build_fail()
{
int head=0,tail=0;
for(int i=0;i<26;i++)
{
if(ch[0][i])
{
que[++tail]=ch[0][i];
}
}
while(head<tail)
{
int u=que[++head];
for(int i=0;i<26;i++)
{
if(ch[u][i])
{
fail[ch[u][i]]=ch[fail[u]][i];
que[++tail]=ch[u][i];
}
else ch[u][i]=ch[fail[u]][i];
len[ch[u][i]]=min(len[ch[u][i]],len[fail[ch[u][i]]]);
}
}
}
int main()
{
int n;
memset(len,inf,sizeof(len));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
ins(s);
}
build_fail();
scanf("%s",s);
int root=0;
int sta[maxn];
int p=0;
sta[++p]=root;
printf("%d\n",len[sta[p]]);
for(int i=0;s[i];i++)
{
if(s[i]=='-')
{
if(p) p--;
root=sta[p];
}
else
{
int x=s[i]-'a';
root=ch[root][x];
sta[++p]=root;
}
printf("%d\n",len[sta[p]]);
}
return 0;
}
本文介绍如何使用AC自动机优化单词匹配问题,通过构建Trie图并利用失败指针更新节点答案,实现输入字母后快速计算最少需要添加的单词数。代码示例展示了完整的AC自动机构建及查询过程。
7596

被折叠的 条评论
为什么被折叠?



