1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
对所有单词建立ac自动机。然后跑一边就完事了。
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define ll long long struct Node{ Node*ch[27],*fail; int mark,id; }word[600001];//´æ×ÖµäÊ÷ int cnt; Node *super,*root;// Node*newNode(){//²åÈë×Ö·û´® memset(&word[cnt],0,sizeof(word[0])); word[cnt].id = cnt; return &word[cnt++]; } void insert(Node*root,char*s){//½¨Ê÷ if(*s==0){ root->mark++; return; } int id = *s-'a'; if(root->ch[id] == 0) root->ch[id] = newNode(); insert(root->ch[id],s+1); } void build(Node*root){// for(int i = 0;i < 27;i++) super->ch[i] = root; root->fail = super; queue<Node*>Q; Q.push(root); while(!Q.empty()){ Node* q = Q.front(); Q.pop(); for(int i = 0;i < 27; i++){ if(q->ch[i] != NULL){ Q.push(q->ch[i]); q->ch[i]->fail = q->fail->ch[i]; q->ch[i]->mark += q->fail->ch[i]->mark; } else q->ch[i] = q->fail->ch[i]; } } } ll autofind(char *s){ ll ans = 0,id; Node*rt = root,*p; while(*s){ id = *s - 'a'; if(rt->ch[id] != root) rt = rt->ch[id]; else{ while(rt != root && rt->ch[id] == root) rt = rt->fail; } ans += rt->mark; s++; if(*s == 'a'+26){ printf("%I64d\n",ans); ans = 0; } } return ans; } char sen[400007]; char wor[400007]; int main(){ int t,n,m; scanf("%d",&t); while(t--){ cnt = 0; scanf("%d%d",&n,&m); int len = 0,lex; for(int i = 0;i < n; i++){ scanf("%s",sen+len); lex = strlen(sen+len); len += lex; sen[len] = 'a'+26; len++; } sen[len] = '\0'; super = newNode(); root = newNode(); for(int i = 0;i < m; i++){ scanf("%s",wor); insert(root,wor); } build(root); ll ans = autofind(sen); //printf("%I64d\n",ans); } return 0; }