hdu5880-ac自动机,超详解析

题意是:给你一些模式串,再给一个文本串,如果在文本串中能够查询到该模式串,就将文本串中的模式串改为 '*'

注意可能会爆内存和字符串的输入。

#include
#include
#include
using namespace std;
const int maxn=1000005;
struct AC{
    int ch[maxn][26];
    int cnt[maxn];                   //记录模式串的长度
    int fail[maxn];                  //失败指针
    int tot;
	int q[maxn];                    //q[maxn]在build方法中使用,建立失败指针时会用到,功能和队列差不多,
    void init(){                    //放在build()方法里面,开的数组太大,导致数组溢出,就放结构体了
        memset(ch[0],-1,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        memset(fail,0,sizeof(fail));
        tot=0;
    }
    int newnode()
    {
        tot++;
        memset(ch[tot],-1,sizeof(ch[tot]));
        fail[tot]=0;
        cnt[tot]=0;
        return tot;
    }
    void insert(char *s){
        int p=0;
        for(int i=0;s[i];i++){
            if(ch[p][s[i]-'a']==-1)
                ch[p][s[i]-'a']=newnode();
            p=ch[p][s[i]-'a'];
        }
        cnt[p]=strlen(s);            //记录下该模式串的长度,在接下来的文本串查找中,将会使用。
    }
    /*void insert(char *s){          //一开始选择使用这种插入方法,导致内存直接溢出,大概84000k
        int p=0;                     //,换了插入之后48000k如果有更好的插入方法,欢迎指出
        for(int i=0;s[i];i++){
            if(ch[p][s[i]-'a']==-1)
                ch[p][s[i]-'a']=++tot;
            p=ch[p][s[i]-'a'];
        }
        cnt[p]=strlen(s);
    }*/
    void build(){                  //建立失败指针,一般使用队列,怎么说,用l和r这种方法和队列各有好坏吧!
        int l=0,r=0;
        for(int i=0;i<26;i++){
            if(ch[0][i]==-1)
                ch[0][i]=0;
            else{
                q[r++]=ch[0][i];
            }
        }
        while(l='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z')
            {
                if(s[i]>='A'&&s[i]<='Z')
                    p=ch[p][s[i]-'A'];
                else
                    p=ch[p][s[i]-'a'];
                int tmp=p;
                while(tmp!=0){                  //如果存在该模式串
                    for(int j=0;j

 

你可能感兴趣的:(AC自动机)