您的位置:首页 > 其它

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

2017-08-17 18:39 483 查看
题意:给出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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息