7758. Growing StringsProblem code: MGLAR10 |
English | Vietnamese |
Input
Each test case is given using several lines. The first line contains an integer N representing the number of strings in the set (1 ≤ N ≤ 10^4). Each of the following N lines contains a different non-empty string of at most 1000 lowercase letters of the English alphabet. Within each test case, the sum of the lengths of all strings is at most 10^6.
The last test case is followed by a line containing one zero.
Output
For each test case output a single line with a single integer representing the size of the largest sequence of photos that can be produced.
Sample
input 6 plant ant cant decant deca an 2 supercalifragilisticexpialidocious rag 0 output 4 2
-----------
题目给定n个字符串,让我们找出若干个字符串组成一个序列,前面一个字符串是后面一个字符串的子串,问我们能获得得最长序列的长度。
最长串为temp的子节点时能获得的最长序列长度=max(其父节点的长度,其fail指针指向的节点的长度)+以该节点结尾的单词的数量
temp->next[i]->sum=max( temp->sum, temp->next[i]->fail->sum )+temp->next[i]->count;
-----------
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
const int CHARSET = 26;
const int MAX_N_NODES = 2111111;
struct Aho_Corasick{
struct Node{
Node *next[CHARSET];
Node *fail;
int count;//记录当前前缀是完整单词出现的个数
int sum;
Node(){
memset(next,0,sizeof(next));
fail = NULL;
count = 0;
sum=0;
}
void clear(){
memset(next,0,sizeof(next));
fail = NULL;
count = 0;
sum=0;
}
};
queue<Node*>Q;
Node *root;
Node nodePool[MAX_N_NODES], *cur;
Node* newNode(){
Node* t=cur++;
t->clear();
return t;
}
void init(){
cur=nodePool;
root=newNode();
}
void insert(char *str){
Node* p=root;
int index;
int len=strlen(str);
for (int i=0;i<len;i++){
index=str[i]-'a';
if(p->next[index]==NULL) p->next[index]=newNode();
p=p->next[index];
}
p->count++;
}
void build_ac_automation(){
int i;
while (!Q.empty()) Q.pop();
root->fail=NULL;
Q.push(root);
while(!Q.empty()){
Node* temp=Q.front();
Q.pop();
Node* p=NULL;
for(i=0;i<CHARSET;i++){
if(temp->next[i]!=NULL){//寻找当前子树的失败指针
if (temp==root){
temp->next[i]->fail=temp;
temp->next[i]->sum=temp->sum+temp->next[i]->count;
}
else{
p = temp->fail;
while(p!=NULL){
if(p->next[i]!=NULL){//找到失败指针
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) temp->next[i]->fail=root;//无法获取,当前子树的失败指针为根
//==========
temp->next[i]->sum=max( temp->sum, temp->next[i]->fail->sum )+temp->next[i]->count;
//==========
}
Q.push(temp->next[i]);
}
}
}
}
int query(){//询问str中包含n个关键字中多少种即匹配
int res=-1;
for (Node* it=nodePool;it!=cur;it++){
res=max(res,it->sum);
}
return res;
}
}AC;
int main()
{
char s[21111];
int n;
while (~scanf("%d",&n)){
if (n==0) break;
getchar();
AC.init();
for (int i=0;i<n;i++){
//scanf("%s",s);
gets(s);
AC.insert(s);
}
AC.build_ac_automation();
int ans=AC.query();
printf("%d\n",ans);
}
return 0;
}