链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3695
题目大意:
给出n个匹配串,然后给一个长串S,找出S中有多少种匹配串。注意匹配串在S中正反出现的顺序都算是出现。
S可能会有些段是压缩过的,格式为【qx】,q是一个数字,x是一个字母,代表有q个x。 假设 把B【3A】DE“解压缩”之后,就是
BAAADE
分析与总结:
一开始没弄清题意,以为是求所有病毒的总数量,结果一直TLE。。其实这题要求的是源码中有多少种病毒。一旦找到一个病毒,就把Trie中的那个单词标记为false.
另外把“压缩”的网站源码进行“解压缩”的步骤也要细心点,容易出错。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN = 5200005; const int MAX_NODE = 3000005; const int SIGMA_SIZE = 26; char str[MAXN]; char buf[MAXN]; struct node{ node* fail; node* next[SIGMA_SIZE]; bool isword; int id; void init(){ id=0; isword=false; memset(next, 0, sizeof(next)); } }; class AC_Automation{ public: void init(); void insert(char*,int); void getFail(); int find(char*); private: node* new_node(); int ID(char ch){return ch-'A';} private: node Heap[MAX_NODE]; node* root; int size; }; node* AC_Automation::new_node(){ Heap[size].init(); return &Heap[size++]; } void AC_Automation::init(){ size=0; root=new_node(); } void AC_Automation::insert(char* str,int id){ node* p=root; for( ; *str; ++str){ int ch=ID(*str); if(p->next[ch] == NULL) p->next[ch] = new_node(); p = p->next[ch]; } p->isword=true; p->id=id; } void AC_Automation::getFail(){ queue<node*>Q; Q.push(root); while(!Q.empty()){ node* tmp=Q.front(); Q.pop(); for(int i=0; i<SIGMA_SIZE; ++i){ node*& now = tmp->next[i]; if(now != NULL){ Q.push(now); if(tmp==root) now->fail=root; else{ node* p=tmp->fail; while(p != NULL){ if(p->next[i] != NULL){ now->fail = p->next[i]; break; } p = p->fail; } if(p==NULL) now->fail=root; } } else{ if(tmp==root) now = root; else now=tmp->fail->next[i]; } } } } int AC_Automation::find(char* str){ node* p=root; int cnt=0; for( ; *str; ++str){ int ch=ID(*str); p = p->next[ch]; if(p==NULL) p=root; node* tmp=p; while(tmp!=root && tmp->isword){ ++cnt; tmp->isword=false; tmp = tmp->fail; } } return cnt; } // 字符串转置 inline void rev(char* str, int len){ char ch; for(int i=0, k=len-1; i<len/2; ++i,--k){ ch=str[i]; str[i]=str[k]; str[k]=ch; } } // 字符串“解压缩” inline void change(char* str,char* now){ memset(now, 0, sizeof(now)); int len=strlen(str); int i; for(i=0; i<len; ++i){ if(str[i]=='['){ ++i; int num=0; while(str[i]>='0' && str[i]<='9'){ num = num*10 + str[i] - '0'; ++i; } while(num--){ *now = str[i]; ++now; } ++i; } else{ *now=str[i]; ++now; } } } AC_Automation ac; int main(){ int n,nCase; char pat[1005]; scanf("%d",&nCase); while(nCase--){ ac.init(); scanf("%d%*c",&n); for(int i=1; i<=n; ++i){ gets(pat); ac.insert(pat, i); } ac.getFail(); memset(buf, 0, sizeof(buf)); memset(str, 0, sizeof(str)); gets(buf); change(buf,str); int ans=ac.find(str); rev(str,strlen(str)); printf("%d\n", ans+ac.find(str)); } return 0; }
—— 生命的意义,在于赋予它意义士。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)