AC自动机(板子总结)

板子来源

https://www.cnblogs.com/hefenghhhh/p/5051334.html

https://www.cnblogs.com/Simon-X/p/5687318.html

心得

去年九月份学过的知识,

就不再详细展开了,

大概就是树上的KMP

以前总用指针的,不好写,100多行,

今天也搞一个数组的板子

然后每个trie都是一个节点,节点与next关系共同构成了树

AC自动机的题比较板子化,

数组空间开大了的话会MLE

数组空间开大了多组数据要memset的话可能还会TLE

可是数组真的好用啊

亲测之后,是纯数组最快,

但抄来的板子的命名风格是OI爷的代码风格,可读性QAQ啊

板子1(结构体+数组 hdu2896 病毒侵袭)

#include
#include
#include
using namespace std;
struct node
{
  int id,fail,Next[130];       
}trie[100010];
char word[202],web[10005];
int head,tail,tot,root;
int que[100010],ans[502];
int Virus,Webs,res[10];
int n,m;
void insert(int r,char *s,int id)//(root,串,串号) 
{
   int len=strlen(s);
   for(int i=0;i0)ans[trie[tempfail].id]=1;
         }
     }
}
int main()
{
    root=tot=1;
    scanf("%d",&n);
    for(int i=0;i

板子2(指针 hdu2222 Keywords Search)

#include
#include
#include 
#include 
using namespace std;
struct acnode{
    int sum;
    acnode* next[26];
    acnode* fail;
    acnode(){
        for(int i =0;i<26;i++)
            next[i]=NULL;
        fail= NULL;
        sum=0;
    }
};
acnode *root;
int cnt;
char s[1000005],tmp[50];
acnode* newnode(){
    acnode *p = new acnode();
    return p;
}
//插入函数
void Insert(char *s)
{
    acnode *p = root;
    for(int i = 0; s[i]; i++)
    {
        int x = s[i] - 'a';
        if(p->next[x]==NULL)
        {
            acnode *nn=newnode();
            p->next[x]=nn;
        }
        p = p->next[x];
    }
    p->sum++;
}
//获取fail指针,在插入结束之后使用
void getfail(){
    queue q;
	for(int i = 0 ; i < 26 ; i ++ )
	{
		if(root->next[i]!=NULL){
			root->next[i]->fail = root;
			q.push(root->next[i]);
		}
	}
    while(!q.empty()){
        acnode* tem = q.front();
        q.pop();
        for(int i = 0;i<26;i++){
            if(tem->next[i]!=NULL)
            {
                acnode *p;
                if(tem == root){
                    tem->next[i]->fail = root;
                }
                else
                {
                    p = tem->fail;
                    while(p!=NULL){
                        if(p->next[i]!=NULL){
                            tem->next[i]->fail = p->next[i];
                            break;
                        }
                        p=p->fail;
                    }
                    if(p==NULL)
                        tem->next[i]->fail = root;
                }
                q.push(tem->next[i]);
            }
        }
    }
}
//匹配函数
void ac_automation(char *ch)
{
    acnode *p = root;
    int len = strlen(ch);
    for(int i = 0; i < len; i++)
    {
        int x = ch[i] - 'a';
        while(p->next[x]==NULL && p != root)//没匹配到,那么就找fail指针。
            p = p->fail;
        p = p->next[x];
        if(!p)
            p = root;
        acnode *temp = p;
        while(temp != root)
        {
           if(temp->sum >= 0)
            /*
            在这里已经匹配成功了,执行想执行的操作即可,怎么改看题目需求+
            */
           {
               cnt += temp->sum;
               temp->sum = -1;
           }
           else break;
           temp = temp->fail;
        }
    }
}
void Delete(acnode* root)
{
	for(int i=0;i<26;++i)if(root->next[i])Delete(root->next[i]);
	delete root;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
    	cnt=0;
    	root=newnode();
    	scanf("%d",&n);
    	for(int i=0;i

板子3(纯数组 hdu3065魔改而来)

#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxl=2e6+5;
const int maxm=1e3+5;
const int maxn=50005;
//trie是节点 fail是指针 num是节点出现串的个数
//s是读入的要被插入trie树的串 t是要匹配的串
int n,cnt; 
int trie[maxn][26],fail[maxn],num[maxn];
char s[maxm][55],t[maxl];
void build(int n)
{
    memset(trie,0,sizeof trie);
	memset(fail,0,sizeof fail);
    memset(num,0,sizeof num);
    cnt=0;
    for(int i=1,now=0;i<=n;++i)
	{
        gets(s[i]);
        for(int j=0;s[i][j];++j)
		{
            int ch=s[i][j]-'A';
            if(!trie[now][ch])trie[now][ch]=++cnt;
            now=trie[now][ch];
        }
        num[now]=i;
    }
}
void setFail()
{
    queueq;
    for(int i=0;i<26;++i)
	if(trie[0][i])q.push(trie[0][i]);
	while(!q.empty())
	{
        int now=q.front();
		q.pop();
        for(int i=0;i<26;++i)
		{
			int &to=trie[now][i];
            if(to)
			{
			 q.push(to);
			 fail[to]=trie[fail[now]][i];
            }
			else trie[now][i]=trie[fail[now]][i];
        }
    }
}
ll solve()
{
    gets(t);
	ll ans=0;
    for(int i=0,j=0;t[i];++i)
	{
        if(t[i]<'A'||'Z'

 

你可能感兴趣的:(知识点总结)