/** 題目:zoj3228 Searching the String 連接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441 題意:給定一個長度爲N(N <= 105)的目標串,而後再給定M(M <= 105)個長度不大於6的字符串, 問這些字符串在目標串的出現次數(分可重疊和不可重疊兩種)。 題解:能夠覆蓋狀況下,直接創建自動機求次數。注意可能出現類型相同以及字符串相同。因此用map標記; 不能夠覆蓋狀況下,直接創建自動機,查詢的時候維護當前查到的字符串上一次找到的位置lastpos. 若是lastpos+該子串長度<=pos那麼能夠ans++,以及更新lastpos=pos; find(),find2()兩個函數分別處理可覆蓋,不可覆蓋狀況。先統一處理可覆蓋,而後清空自動機從新構建不可覆蓋狀況下的自動機。 AC自動機好文章:http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html */ //#include<bits/stdc++.h> #include<cstring> #include<cstdio> #include<iostream> #include<map> #include<algorithm> #include<queue> using namespace std; #define P pair<int,int> #define ms(x,y) memset(x,y,sizeof x) #define LL long long const int maxn = 1005; const int mod = 1e9+7; const int maxnode = 100000*6+10; const int sigma_size = 26; map<string,int> mp1, mp2; struct node { char s[7]; int type; int len; int ans; int lastpos; }t[100005]; struct AhoCorasickAutomata { int ch[maxnode][sigma_size]; int val[maxnode]; int sz; int f[maxnode]; int last[maxnode]; void clear(){sz = 1; memset(ch[0],0,sizeof ch[0]); } int idx(char c){return c-'a'; } void insert(char *s,int x) { int u = 0, n = strlen(s); for(int i = 0; i < n; i++){ int c = idx(s[i]); if(!ch[u][c]){ memset(ch[sz], 0, sizeof ch[sz]); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = x; } void find(char* T){ int j = 0; for(int i = 0; T[i]!='\0'; i++){ int c = idx(T[i]); j = ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); } } void print(int j) { if(j){ //cnt[val[j]]++; t[val[j]].ans++; print(last[j]); } } void find2(char* T){///不可覆蓋狀況下; int j = 0; for(int i = 0; T[i]!='\0'; i++){ int c = idx(T[i]); j = ch[j][c]; if(val[j]) print2(j,i); else if(last[j]) print2(last[j],i); } } void print2(int j,int pos) { if(j){ //cnt[val[j]]++; if(t[val[j]].lastpos+t[val[j]].len<=pos){ t[val[j]].ans++; t[val[j]].lastpos = pos; } print2(last[j],pos); } } void getFail(){ queue<int> q; f[0] = 0; for(int c = 0; c < sigma_size; c++){ int u = ch[0][c]; if(u){f[u] = 0; q.push(u); last[u] = 0;} } while(!q.empty()){ int r = q.front(); q.pop(); for(int c = 0; c < sigma_size; c++){ int u = ch[r][c]; if(!u){ ch[r][c] = ch[f[r]][c]; continue; }//if(!u) continue; q.push(u); int v = f[r]; while(v&&!ch[v][c]) v = f[v]; f[u] = ch[v][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } } } } ac; char s[100005]; int main() { int cas = 1; while(scanf("%s",s)==1) { int n; scanf("%d",&n); ac.clear(); mp1.clear(); mp2.clear(); for(int i = 1; i <= n; i++){ scanf("%d%s",&t[i].type,t[i].s); t[i].ans =0 ; if(t[i].type==0){ mp1[string(t[i].s)] = i; ac.insert(t[i].s,i); } } ac.getFail(); ac.find(s); ac.clear(); mp2.clear(); for(int i = 1; i <= n; i++){ if(t[i].type){ t[i].len = strlen(t[i].s); t[i].lastpos = -1; mp2[string(t[i].s)] = i; ac.insert(t[i].s,i); } } ac.getFail(); ac.find2(s); printf("Case %d\n",cas++); for(int i = 1; i <= n; i++){ if(t[i].type){ printf("%d\n",t[mp2[t[i].s]].ans); }else { printf("%d\n",t[mp1[t[i].s]].ans); } } printf("\n"); } return 0; } /* */