题意:

给出n个字符串,再给出一个字符串,把之前出现过的字符串全部变成*

思路:

AC自动机,Trie树上存的值是一个字符串的长度,也就是往前的长度,然后倒着处理一遍。

感想:

第三题AC自动机,本来就是想脱离模板多练练,虽然之前撒比bug错了一大堆,但是收获很多啊。

重要的感想有两个方面:

一:

在我们solve主串的时候:

在通过移动失败指针处理后缀串的时候,在这道题里只要找到一个就行了。

看了网上,主要有两种标记方法(其实类似),其中一种就是通过标记这个位置最长后缀来处理,这样完全可行,然而那个博主的处理方法并不合适,

那个博主的方法是在通过移动失败指针处理后缀串的时候,还在比较取这个位置的后缀串最大,其实理解的话,我们完全不需要比较啊,理由:这个后缀串本身就是你的子串,何必啊???而且在通过移动失败指针处理后缀串的时候第一个即最长。

二:

一开始无脑在线printf,本身就是比较费时的写法,然后就靠评测机抖一抖AC,直接先转变好,一发printf,妥妥的省了一堆时间。

(三:

模板还是网赛用用吧???

//#include <bits/stdc++.h>
#include<iostream>
#include<queue>
#include<string.h>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL; const int N=1e6+10;
struct Trie{
int num;
Trie *next[27],*fail;
};
Trie q[N],*root;
int tol;
char word[N],str[N];
//int latersum[N];//第一种方法
int flag[N];//第二种方法 Trie* Creat()
{
Trie *p;
p=&q[tol++];
p->num=0;
p->fail=NULL;
for(int i=0;i<26;i++)
p->next[i]=NULL;
return p;
} void Insert()
{
Trie* p=root;
int len=strlen(str),index;
for(int i=0;i<len;i++)
{
index=str[i]-'a';
if(p->next[index]==NULL)
p->next[index]=Creat();
p=p->next[index];
}
p->num=len;
} void Build_Ac()
{
queue<Trie*>que;
que.push(root);
while(!que.empty())
{
Trie *p=que.front();que.pop();
for(int i=0;i<26;i++)
{
if(p->next[i]!=NULL)
{
if(p==root)
p->next[i]->fail=root;
else
{
Trie* temp=p->fail;
while(temp!=NULL)
{
if(temp->next[i]!=NULL){
p->next[i]->fail=temp->next[i];
break;
}
temp=temp->fail;
}
if(temp==NULL)
p->next[i]->fail=root;
}
que.push(p->next[i]);
}
}
}
} void Query()
{
int len=strlen(word),index; Trie *p=root;
for(int i=0;i<len;i++)
{
// latersum[i]=0;
flag[i]=0;
if(!((word[i]>='a'&& word[i]<='z')||(word[i]>='A'&&word[i]<='Z')))
continue;
index=(word[i]>='A'&&word[i]<='Z')?(tolower(word[i])-'a'):(word[i]-'a');
while(p->next[index]==NULL && p!=root)
p=p->fail;
p=p->next[index];
if(p==NULL)
p=root;
Trie *temp=p;
while(temp!=root)
{
if(temp->num){
// flag[i]=max(flag[i],temp->num);
flag[i]=temp->num;
// latersum[i+1]--;
// latersum[i-temp->num+1]++;
break;//第一个后缀一定是最长的,不需要在转移到别的fail指针
}
temp=temp->fail;
}
}
// int nn=0;//无脑printf,此代码要看天命AC
// for(int i=0;i<len;i++)
// {
// nn+=latersum[i];
//// if(nn<=0)
//// printf("%c",word[i]);
//// else
// if(nn>0)
// word[i]='*';
// }
// puts("");
int nn=0;
for(int i=len-1;i>=0;i--)
{
nn=max(nn,flag[i]);
if(!nn) continue;
else{
word[i]='*';
nn--;
}
}
printf("%s\n",word);
} int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
tol=0;
root=Creat();
while(n--)
{
scanf("%s",str);
Insert();
}
getchar();
Build_Ac();
gets(word);
Query();
}
return 0;
}

HDU5880【AC自动机】的更多相关文章

  1. HDU5880 Family View ac自动机第二题

    Steam is a digital distribution platform developed by Valve Corporation offering digital rights mana ...

  2. ac自动机暴力跳fail匹配——hdu5880

    很简单的题,ac自动机里再维护一个len表示每个状态的串长,用s去query时每到一个结点都要暴力跳fail,因为有可能这个结点不是,但是其fail是危险结点,找到一个就直接break 再用个差分数组 ...

  3. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  4. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  5. python爬虫学习(11) —— 也写个AC自动机

    0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  7. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  8. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  9. [AC自动机]【学习笔记】

    Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...

随机推荐

  1. Oracle中Hint深入理解

    Hint概述 基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担.但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比. 此时就需要DBA进行 ...

  2. 辛星浅析html5中的role属性

    我们使用role属性告诉辅助设备.这个元素所扮演的角色.比方点击的按钮,我们通常就使用role="button",会让这个元素可点击. 可是它很多其它的是用来增强语义性,当现有的h ...

  3. SAM4E单片机之旅——1、LED闪烁之空循环

    最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书.现在也让我写写几个小的程序,做做示例.既然写了文档之类的,就发到博客上来吧. 目前关于这芯片能参考的书籍大概就只 ...

  4. Qt中的打印操作

    Qt中对打印的支持是有一个独立的printsupport模块来完成的,所以,要想在程序中使用Qt的打印功能,必须先在pro文件中添加下面这句代码: QT += printsupport在这个模块中,提 ...

  5. PPTP&L2TP&PPPOE client and server configure

    一. PPPOE 1. server(参考http://laibulai.iteye.com/blog/1171898) (1)安装rp-pppoe:yum install rp-pppoe (2)配 ...

  6. SQL 系统表应用

    查看link server select DD.System,DD.DB,DD.previous_processing_dte, DD.processing_dte,LS.LinkServerName ...

  7. 剑指Offer:重建二叉树【7】

    剑指Offer:重建二叉树[7] 题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5 ...

  8. sdut oj 3058 路线冲突问题(BFS+记录路径算法,回溯路径 )

    路线冲突问题 题目描述 给出一张地图,地图上有n个点,任意两点之间有且仅有一条路.点的编号从1到n. 现在兵团A要从s1到e1,兵团B要从s2到e2,问两条路线是否会有交点,若有则输出交点个数,否出输 ...

  9. APP测试走过的那些坑

    我现在的工作有一大部分也是app测试,虽然自己是app开发出身,但是在测试上还是跌入了很多大坑,毕竟二者还是有很大不同,所处的角度也是不一样的.而开发转测试中,我认为较难的也是一个角度的转换,以一个开 ...

  10. python 实用pickle序列化

    存储数据结构到一个文件中称为序列化.相json这样的格式需要定制的序列化数据的转换器.python提供了pickle模块以特殊的二进制格式保存和恢复数据对象. 还记得json解析datetime对象时 ...