【ZOJ3228】白濑肆の完美算法教室补番作,0.7%达成 白濑肆×AC自动机
2012-08-20 01:51
429 查看
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <queue> using namespace std; /** 就是一个AC自动机 但是每个单词有两个状态,[0]是可以overlap,[1]是不能overlap时候的次数 我们用last数组记录下每个不能overlap的单词出现的位置,如果 当前位置 - last[word] + 1 > strlen(word),那么证明该单词并未overlap,更新last数组,对应次数+1即可 补番作,水题。 */ const int MAX_ALPHABET = 27; const int MAX_TEXT = 100010; const int MAX_WORD = 7; const int MAX_WORD_NUM = 100010; struct node { int id; int cnt; int len; node* fail; node* next[MAX_ALPHABET]; node() { id = -1; //指定该单词出现的位置。 cnt = 0; fail = NULL; len = 0; memset(next,0,sizeof(next)); } }; int cnt; int loc[MAX_WORD_NUM]; int type[MAX_WORD_NUM]; int strcnt[MAX_WORD_NUM][2]; // 每个词儿两个状态 int last[MAX_WORD_NUM]; //每个词最后一次出现的地方。 queue<node*> q; ////变量区结束/// int AC_insert(node* root,char* dest,int flag) { node* tmp = root; int l = strlen(dest); for(int i = 0 ; i < l ; i++) { int k = dest[i]-'a'; if( tmp->next[k] == NULL ) { tmp->next[k] = new node(); } tmp = tmp->next[k]; } if( tmp->id == -1) { tmp->id = cnt; cnt++; } tmp->cnt = tmp->cnt | flag; tmp->len = l; return tmp->id; //标明该单词在单词列表中第几个出现。。。 } void AC_build(node* root) { root->fail = NULL; q.push(root); while(!q.empty()) { node* tmp = q.front(); q.pop(); node *p; for(int i = 0 ; i < 26 ; i++) { if(tmp->next[i]) { if( tmp == root ) { tmp->next[i]->fail = root; } else { p = tmp->fail; while(p) { if( p->next[i] ) { tmp->next[i]->fail = p->next[i]; break; } p = p->fail; } if( !p ) tmp->next[i]->fail = root; } q.push(tmp->next[i]); } } } } void AC_search(node* root,char* dest) { node* tmp; node* p; p = root; for(int i = 0 ; dest[i] ; i++) { int ind = dest[i] - 'a'; while( p->next[ind]==NULL && p != root) p = p->fail; p = p->next[ind]; if( p == NULL ) p = root; tmp = p; while( tmp != NULL ) { if( tmp->id != -1 ) { if( tmp->cnt & 1 ) { strcnt[tmp->id][0]++; } if( tmp->cnt & 2 ) { if( i - tmp->len + 1 > last[tmp->id] ) { strcnt[tmp->id][1]++; last[tmp->id] = i; } } } tmp = tmp->fail; } } } int main() { #ifndef ONLINE_JUDGE freopen("B:\\acm\\SummerVacation\\String-I\\B.in","r",stdin); freopen("B:\\acm\\SummerVacation\\String-I\\B.out","w",stdout); #endif char dest[MAX_TEXT]; char word[MAX_WORD]; int t = 1; while(scanf("%s",dest) != EOF) { memset(last,-1,sizeof(last)); memset(strcnt,0,sizeof(strcnt)); cnt = 1; node* root = new node(); int N; scanf("%d",&N); for(int i = 0 ; i < N ; i++) { scanf("%d %s",&type[i],word); loc[i] = AC_insert(root,word,type[i]+1); } AC_build(root); AC_search(root,dest); printf("Case %d\n",t++); int ans; for(int i = 0 ; i < N ; i++) { ans = strcnt[loc[i]][type[i]]; printf("%d\n",ans); } printf("\n"); } #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }
相关文章推荐
- 【ZOJ3587】Marlon's String——白四爷×KMP 白濑肆の算法完全解读KMP篇 KMP来袭第二弹前缀什么的果然最讨厌了!【1.0%达成!】
- Aho-Corasick自动机算法(AC算法解读)
- BIT琪露诺的完美算法教室 2.hybest的A+B(2)
- 【HDU4313】Matrix 多校 解题报告+AC代码+思路+算法正确性证明,此为Kruskal贪心简单版本,恶心版本稍后放出【目标达成 0.2%】
- AC自动机算法详解
- 【HDU4313】Matrix 多校 解题报告+AC代码+思路+算法正确性证明,此为Kruskal贪心恶心版本,非自虐倾向慎入!建议想找解题报告的童鞋看简单版本的,这个我写给自己【目标达成 0.2%】
- [转]AC自动机算法详解
- 【常用经典算法总结系列一】AC自动机
- 【CodeForces 155C Hometask】白濑肆×字符串+DP——果然是字符串处理什么的好讨厌啊尤其是换行符的处理看来不用CIN不行了呢DP的转移真心不会啊水到家了怎么办!【1.1%达成】
- BIT琪露诺的完美算法教室 3.初上征途的za
- AC自动机算法详解
- AC自动机算法详解
- 字符串系列3 Boyer-Moore 算法和 AC 自动机
- AC自动机算法详解
- [原创]字符串多模匹配算法之AC自动机理解心得
- [置顶] AC自动机算法与AC自动机专辑
- kuangbin专题十七 ZOJ3228 AC自动机不可重叠计算
- BIT琪露诺的完美算法教室 4.吃货的烦恼
- AC自动机算法详解
- AC自动机算法详解