AC自动机--尚需努力

  AC自动机,名字很酷(我就是奔着这名字去的),其实就比字典树多了一个fail指针,什么是fail指针呢,就是串对字典树匹配失配时字典树节点下一步往哪指。是不是和KMP有点像,呵呵,没错,就是KMP的思想,假设该节点是u,它的fail指针指向v,v就是一个和u的字母一样,并且从根出发到v形成的字符串和从根到u的路径上的某一处到u形成的字符串相同的节点。呵呵,有点麻烦,其实求的时候就是一个递推的过程,root的fail指针是NULL,某一个节点u的fail指针就是它的父节点的fail指针指向的节点(以下简称x节点)的u孩子(u孩子就是指一个节点的孩子中的一个和u的字母一样的孩子),如果x没有u孩子,按x的fail指针继续往上找。直到找到,如果找到root仍没有,u的fail指针就指向root。代码可描述为:

struct Trie{

	int count;

	struct Trie *fail;

	struct Trie *next[26];

} *root,*queue[500005];

void get_fail()

{

    int start = 0,end = 1,i;

    struct Trie *p = root,*q;

    root->fail = NULL; root->count = -1;

    queue[start] = p;

    while (start < end){

    p = queue[start];

    for (i = 0; i< 26; i++){

        if (p->next[i] != NULL){

            queue[end++] = p->next[i];

             q = p;

              while (q->fail != NULL){

                     if (q->fail->next[i] != NULL){

                         p->next[i]->fail = q->fail->next[i];

	        break;

                      }

                      else q = q->fail;

              }

              if (q->fail == NULL) p->next[i]->fail = root;

        }

    }

    start++;

  }

}

至于匹配,和KMP差不多啦,代码为

void search(int x,int y,int k)

{

	int x1 = x,y1 = y;

	struct Trie *p = root,*q;

	while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m){

		int id = map[x1][y1] - 'A';

		while (p->next[id] == NULL && p->fail != NULL) p = p->fail;

		p = p->next[id]; p = (p == NULL)?root:p; q = p;

		while (q != root && q->count != -1){

			result[q->count][0] = x1-lenth[q->count]*dir[k][0]; result[q->count][1] = y1-lenth[q->count]*dir[k][1];

			ans[q->count] = k + 'A'; q->count = -1; q = q->fail;

		}

		x1 += dir[k][0]; y1 += dir[k][1];

	}

}

至于题,下次发吧!下午还有万恶的比赛。。。。

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