HDU 6138 2017多校第八场1006 Fleet of the Eternal Throne :AC自动机

来源:互联网 发布:淘宝客推广招聘 编辑:程序博客网 时间:2024/06/03 13:22

题意:给出n(<=1e5)个串(总长度<=1e5),以及q(<=300,数据有点弱,q改成1e5才好)次询问,每次询问给出x和y,表示输入的第x个和第y个串,要求找出一个最长的字串p,满足:p是x的字串,p是y的字串,且p是这n个串中某一个(可以是多个)的前缀,输出这个最大的长度。

题解:对n个串造出 自动AC机 ,这里的AC机不需要维护单词的结束点  需要维护一个每个节点到根的距离,也就是前缀的长度。然后用x跑一遍AC机,在所有匹配成功的结束节点上记上一个标记(直接记成询问次数就行了:第一次询问flag记成1,第二次记成2,这样保证每次的flag都不一样就不用清空标记了),然后这些标记点的意思就是:这个前缀是n个串中某个的前缀,且这个前缀是串x的字串。然后再用y跑一次AC机,在y匹配成功的节点,如果他刚刚被打了标记,那就统计最长的length就可以。


十分钟手切的自动AC机,在剩下最后五分钟的时候,过了样例就直接交了,然后队友一直在刷新Ranklist,突然发现A了。。。妈耶。。这太惊悚了有木有


Code:

#include<bits/stdc++.h>using namespace std;const int MAX = 100005;struct AC{AC* nxt[26];AC* fail;int length;int flag;};AC* root;int n,q,ans;int index[MAX];char allchar[MAX*10];void clear(AC* node){for (int i=0;i<=25;i++){if (node->nxt[i]!=NULL){clear(node->nxt[i]);}}free(node);}AC* create(){AC* node = (AC*)(malloc(sizeof(AC)));memset(node->nxt,0,sizeof(node->nxt));node->fail = NULL;node->flag = -1;node->length =0;return node;}AC* insert(AC* root,char* word){AC* node = root;char* p = word;while (*p){//cout<<*p<<endl;int id = *p-'a';if (node->nxt[id]==NULL){node->nxt[id]= create();}node->nxt[id]->length = node->length+1;node = node->nxt[id];p ++;}}void init(){if (root!=NULL){clear(root);}root = create();}void input(){scanf("%d",&n);int delta = 0;for (int i=1;i<=n;i++){index[i] = delta;scanf("%s",allchar+delta);insert(root,allchar+delta);delta+=strlen(allchar+delta)+1;}}AC* que[MAX*10];void build(){int l=0;int r=1;que[1]= root;root->fail = root;while (l<r){l++;AC* q = que[l];for (int i=0;i<=25;i++){if (q->nxt[i]!=NULL){if (q==root){q->nxt[i]->fail = root;}else{q->nxt[i]->fail = q->fail;while (q->nxt[i]->fail->nxt[i]==NULL&&q->nxt[i]->fail!=root){q->nxt[i]->fail = q->nxt[i]->fail->fail;}if (q->nxt[i]->fail->nxt[i]!=NULL){q->nxt[i]->fail = q->nxt[i]->fail->nxt[i];}}r++;que[r] = q->nxt[i];}}}}void search(char * word,int f){AC* node = root;char* p = word;while (*p){//cout<<*p<<endl;int id = *p-'a';while (node!=root&&node->nxt[id]==NULL){node = node->fail;}if (node->nxt[id]!=NULL){node = node->nxt[id];}AC* temp = node;while (temp!=root){temp->flag = f;temp = temp->fail;}p++;}}void query(char * word,int f){AC* node = root;char* p = word;while (*p){//cout<<*p<<endl;int id = *p-'a';while (node!=root&&node->nxt[id]==NULL){node = node->fail;}if (node->nxt[id]!=NULL){node = node->nxt[id];}AC* temp = node;while (temp!=root){if (temp->flag ==f){ans = max(ans,temp->length);}temp = temp->fail;}p++;}}void solve(){scanf("%d",&q);for (int i=1;i<=q;i++){int x,y;scanf("%d%d",&x,&y);search(allchar+index[x],i);ans =0;query(allchar+index[y],i);printf("%d\n",ans);}}int main(){int t;scanf("%d",&t);while (t--){init();input();build();solve();}}


原创粉丝点击