AC自动机
(不写写我一会就忘了)
用途:
多个字符串是否在某个(某几个)字符串中出现,出现的次数。。。。
思路:
1.建一棵trie树
2.建fail数组
3.计算
first.建trie树
①申明struct trie{
int son[....]; 字符串的范围 如 小写字母就26
int fail; 失败指针
int id;每个字符串的编号,按输入顺序} A[....]
②insert (char *s,int v)
{
int p=root; L=strlen(s);
for (int i=0;i<L;i++)
{
int x;
x=s[i]-'a';//以小写字母举例
if (A[p].son[x]) p=A[p].son;
else {A[p].son[x]=cnt;p=cnt++;} //cnt 是指那个字符的编号
}
second.求fail
用队列维护
void buildfail(){
p=root; A[p].fail=root;
根的子节点入队,fail指向根。
while(!q.empty()){
int u=q.front(); q.pop();
for (int i=0;i<26;i++)//枚举每个的子节点
if (A[u].son[i])//如果存在
{
int f=A[u].fail;
while(!A[f].son[i]&&f) f=A[f].fail;
if (A[f].son[i]==0) A[A[u].son[i]]=root;
else A[A[u].son]=A[f].son[i];
q.push(A[u].son[i]);
}
}
}
Third 计算
for (int j=0;j<strlen(目标串);j++){
求出串的第j项:i
if (A[p].son[i]) p=A[p].son[i];
else {
int f=A[p].fail;
while(!A[f].son[i]&&f) f=A[f].fail;
if(A[f].son[i]) p=A[f].son[i];else p=0;
}
if (A[p].v) work;
}