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];
	}
}

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

posted on 2010-07-21 11:14  looker  阅读(329)  评论(0编辑  收藏  举报