HDU-2896 病毒侵袭(AC自动机,ascii码匹配)

1、注意是ascii码,不单纯只是字母,所以范围0~127
2、scanf也能过,数据好像没有空格
3、输出total后有换行

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e5 + 5;
const int M = 1e4 + 5;
int trie[N][128]; //字典树
int cntword[N];  //记录该单词出现次数
int fail[N];     //失败时的回溯指针
int num[N];
int tot = 0;
char s[M];
vector<int> vec;
void insertWords(char *s, int l, int t){
    int root = 0;
    for(int i = 0; i < l; ++i){
        int next = s[i];
        if(!trie[root][next])
            trie[root][next] = ++tot;
        root = trie[root][next];
    }
    num[root] = t;
    ++cntword[root];      //当前节点单词数+1
}
void getFail(){
    queue<int> q;
    for(int i = 0; i < 128; ++i){      //将第二层所有出现了的字母扔进队列
        if(trie[0][i]){
            fail[trie[0][i]] = 0;
            q.push(trie[0][i]);
        }
    }

//fail[now]    ->当前节点now的失败指针指向的地方
tire[now][i] -> 下一个字母为i+'a'的节点的下标为tire[now][i]
    while(!q.empty()){
        int now = q.front();
        q.pop();

        for(int i = 0; i < 128; ++i){      //查询26个字母
            if(trie[now][i]){
                //如果有这个子节点为字母i+'a',则
//让这个节点的失败指针指向(((他父亲节点)的失败指针所指向的那个节点)的下一个节点)
                //有点绕,为了方便理解特意加了括号

                fail[trie[now][i]] = trie[fail[now]][i];
                q.push(trie[now][i]);
            }
            else//否则就让当前节点的这个子节点
                //指向当前节点fail指针的这个子节点
                trie[now][i] = trie[fail[now]][i];
        }
    }
}


void query(char *s, int l){
    int now = 0;
    for(int i = 0; i < l; ++i){    //遍历文本串
        now = trie[now][s[i]];  //从s[i]点开始寻找
        for(int j = now; j && cntword[j] != -1; j = fail[j]){
            //一直向下寻找,直到匹配失败(失败指针指向根或者当前节点已找过).
            if(cntword[j] == 1){
            	vec.push_back(num[j]);
            }
        }
    }
}

void init(){
	memset(cntword, 0, sizeof(cntword));
	memset(trie, 0, sizeof(trie));
	tot = 0;
}
int main() {
	int n, cnt = 0;
	scanf("%d", &n);
	getchar();
	for(int i = 1; i <= n; ++i){
	    //gets(s);
	    scanf("%s", s);
		insertWords(s, strlen(s), i);
	}
	fail[0] = 0;
	getFail();
	scanf("%d", &n);
	getchar();
	for(int i = 1; i <= n; ++i){
	    //gets(s);
	    scanf("%s", s);
	    query(s, strlen(s));
	    sort(vec.begin(), vec.end());
	    int tmp = -1, l = vec.size();
		if(l != 0){
		   	++cnt;
	    	printf("web %d:", i);
			for(int k = 0; k < l; ++k){
			    if(vec[k] != tmp){
			    	printf(" %d",vec[k]);
			    	tmp = vec[k];
			    }
			}
			printf("\n");
			vec.clear();
		}
	}
	printf("total: %d\n", cnt);
    return 0;
}


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