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