http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441
trie 这是一个自动机的题 不过trie就可以解决
先对长串进行处理 由于后面出现的字符串最长为6 所以以长串每个位置的字符为起点用长度1-6的子串进行建树
建树时 对树里面的节点要维护 到此节点位置的字符串在原串中出现的位置(多个) 并更新出现的个数和不允许重叠的个数
然后输入短串时就好处理了
代码:
#include <iostream> #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <queue> #include <stack> using namespace std; const int N=1005; const int M=100010; const int K=26; int I; struct node { int v,next; }edge[M*6]; struct nodeTrie { int next[K]; int head; int len; void initialize() { head=-1; len=0; memset(next,-1,sizeof(next)); } }trie[M*6]; int cnt,root; char s[10]; char ls[M]; int num[M*6]; int getNewNode() { ++cnt; trie[cnt].initialize(); return cnt; } void addWord(int p,int l,int r) { for(int i=l;i<r;++i) { if(trie[p].next[ls[i]-'a']==-1) trie[p].next[ls[i]-'a']=getNewNode(); p=trie[p].next[ls[i]-'a']; num[I]=1; ++trie[p].len; edge[I].v=l; edge[I].next=trie[p].head; trie[p].head=I; for(int t=trie[p].head;t!=-1;t=edge[t].next) if(edge[t].v+(i-l+1)<=l) {num[I]=num[t]+1;break;} ++I; } } void init(int n) { cnt=-1;I=0; root=getNewNode(); for(int i=0;i<n;++i) addWord(root,i,min(i+6,n)); } int searchWord(int p,char *s) { for(int i=0;s[i]!='\0';++i) { if(trie[p].next[s[i]-'a']==-1) return 0; p=trie[p].next[s[i]-'a']; } return p; } int findNum(char *s,int flag) { int p=searchWord(root,s); if(p==0) return 0; if(flag==0) return trie[p].len; if(trie[p].len<=1) return trie[p].len; return num[trie[p].head]; } int main() { //freopen("data.in","r",stdin); int ca=0; while(gets(ls)) { ++ca; init(strlen(ls)); int n; scanf("%d",&n); printf("Case %d\n",ca); while(n--) { int flag; scanf("%d ",&flag); gets(s); printf("%d\n",findNum(s,flag)); } printf("\n"); scanf(" "); } return 0; }