算法的详细讲解,请参考
http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
http://www.cnblogs.com/destinydesigner/archive/2009/10/15/1584191.html
推荐 AC自动机算法的 模板题 hdu 2222
1.字典树Trie
建立一个字典树,作用在于压缩信息,更容易求得公共前缀。
2.失配指针
失配指针在于高效地更新公共前缀,利用其中的信息。由BFS的性质以及Trie树的性质可知,若某一序列s[1...m]在m+1处失配时,则该序列更新为s[i...m](i >= 2 && i <= m)。
3.AC自动机
根据之前构建的适配指针,搜索与主串相匹配的模式字符。类似kmp,主串指针一直前进,改变模式串的指针
位置来保证,主串之前的匹配依然成立。
对于一个Trie树,建立失配指针后,Trie树会具有一些特殊的性质:
首先声明几个重要的指针。
1)指针p。指向当前已匹配的字符。若p指向root,则当前匹配的字符序列为空。
2)指针p->fail。指向与p有相同字符的节点,即p的失配指针。
3)指针temp。
对于Trie树中的一个节点,对应一个序列s[1...m]。此时,p指向字符s[m]。若在下一个字符处失配,即p->next[s[m+1]] == NULL,则由失配指针跳到另一个节点(p->fail)处,该节点对应的序列为s[i...m]。若继续失配,则序列依次跳转直到序列为空或出现匹配。在此过程中,p的值一直在变化,但是p对应节点的字符没有发生变化。在此过程中,我们观察可知,最终求得得序列s则为最长公共后缀。另外,由于这个序列是从root开始到某一节点,则说明这个序列有可能是某些序列的前缀。
再次讨论p指针转移的意义。如果p指针在某一字符s[m+1]处失配(即p->next[s[m+1]] == NULL),则说明没有单词s[1...m+1]存在。此时,如果p的失配指针指向root,则说明当前序列的任意后缀不会是某个单词的前缀。如果p的失配指针不指向root,则说明序列s[i...m]是某一单词的前缀,于是跳转到p的失配指针,以s[i...m]为前缀继续匹配s[m+1]。
对于已经得到的序列s[1...m],由于s[i...m]可能是某单词的后缀,s[1...j]可能是某单词的前缀,所以s[1...m]中可能会出现单词。此时,p指向已匹配的字符,不能动。于是,令temp = p,然后依次测试s[1...m], s[i...m]是否是单词。
Keywords Search
Time Limit: 2000/1000 MS (Java/Others)
Total Submission(s): 19147
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.
修改后,正确的模板代码:
//=+
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define kind 26
const int MAXN = 10000000;
struct node
{
};
node *q[MAXN]; //队列,采用bfs 构造失败指针
char keyword[55];//输入单词 模式串
char str[1000010];// 需要查找的 主串
int head,tail;//队列 头尾指针
node *root;
void insert(char *word,node *root)
{
}
void build_ac_automation(node *root)
{
}
int query(node *root)//类似于 kmp算法。
{//i为主串指针,p为匹配串指针
}
int main()
{
}