AC自动机总结
字典树
模板:
const int N = 1000;//长度 //初始化 ac.insert(); //建立字典树 ac.insert(); //建立 fail,last指针 ac.build(); //输入文本串进行统计模式串 ac.query(s); //统计出现次数 ac.getCount(); struct AC_Automata{ int tire[N][4]; int val[N];//结尾标记 int last[N];//last指针 int fail[N];//fail指针 int count[N];//对应字符串 id 的出现次数统计 int tot; void init(){ tot = 1; val[0] = fail[0] = last[0] =0; memset(tire[0],0,sizeof(tire[0])); } void insert(char *s,int v){ int len = strlen(s); int root = 0; for(int i=0;i<len;i++){ int id = get_id(s[i]); if(tire[root][id]==0){ tire[root][id] = tot; memset(tire[tot],0,sizeof(tire[tot])); val[tot++] = 0; } root = tire[root][id]; } val[root] = 1; } void build(){ while(!q.empty()) q.pop(); last[0] = fail[0] = 0; for(int i=0;i<4;i++){ int root = tire[0][i]; if(root!=0){ fail[root] = 0; last[root] = 0; q.push(root); } } while(!q.empty()){ int k = q.front(); q.pop(); for(int i=0;i<4;i++){ int u = tire[k][i]; if(u==0){ tire[k][i] = tire[fail[k]][i]; continue; } q.push(u); fail[u] =tire[fail[k]][i]; last[u] = val[fail[u]]?fail[u]:last[fail[u]]; } } } void getCount(int i){ if(val[i]){ count[val[i]]++; get_count(last[i]); } } void query(char *s){ int len = strlen(s); int j=0; for(int i=0;i<len;i++){ int id = get_id(s[i]); while(j && tire[j][id]==0){ j=fail[j]; } j = tire[j][id]; if(val[j]) getCount(j); else if(last[j]) getCount(j); } } }ac;