hdu 6208(后缀自动机、或者AC自动机
题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串。
思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串。
可以用AC自动机或者后缀自动机做,但是AC自动机用指针的话会MLE,但是我比赛的时候用自己的后缀自动机的板子T了!
然后用了dalao的板子,还是我的板子不够优秀啊(┬_┬)
AC自动机版:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=1e5+;
const int maxm=*;
const int SIGMA_SIZE=;
int n;
char t[maxn],s[maxn]; struct AC
{
int ch[maxm][];
int val[maxm];
int fail[maxm],last[maxm];
int sz;
void clear(){memset(ch[],,sizeof(ch[]));sz=;}
int idx(char x){return x-'a';}
void insert(char *s)
{
int u=;
int n=strlen(s);
for(int i=;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
}
void getfail()
{
queue<int> q;
fail[]=;
int u=;
for(int i=;i<SIGMA_SIZE;i++)
{
u=ch[][i];
if(u){q.push(u);fail[u]=;last[u]=;}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=;i<SIGMA_SIZE;i++)
{
u=ch[r][i];
if(!u){ch[r][i]=ch[fail[r]][i];continue;}
q.push(u);
int v=fail[r];
while(v&&!ch[v][i])v=fail[v];
fail[u]=ch[v][i];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
}
}
}
int find(char *s)
{
int u=,cnt=;
int n=strlen(s);
for(int i=;i<n;i++)
{
int c=idx(s[i]);
u=ch[u][c];
int temp=;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
if(val[u])
temp=u;
else if(last[u])
temp=last[u];
while(temp)
{
cnt+=val[temp];
val[temp]=;
temp=last[temp];
}
}
return cnt;
}
}tree;
string a[maxn];
void solve()
{
scanf("%d",&n);
tree.clear();
int maxx=, id=;
for(int i=;i<=n;i++)
{
scanf("%s",t);
tree.insert(t);
int len=strlen(t);
if (len>maxx) {
maxx=len;
id=i;
}
a[i]=string(t);
}
tree.getfail();
int len=a[id].length();
for (int i=; i<len; i++)
t[i]=a[id][i];
int ans=tree.find(t);
//printf("%d\n",ans);
if (ans==n) puts(t);
else puts("No"); }
int main() {
int t = ;
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
scanf("%d", &t);
while(t--)
solve();
return ;
}
后缀自动机:
/** @xigua */
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#include <queue>
#include <set>
#include <string>
#include <map>
#include <climits>
#define PI acos(-1)
#define rep(a,b,c) for(int (a)=(b); (a)<(c); ++(a))
#define drep(a,b,c) for(int (a)=(b); (a)>(c); --(a))
#define CLR(x) memset(x, 0, sizeof(x))
#define sf scanf
#define pf printf
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + ;
const int ma = 1e5 + ;
const int mod = 1e9 + ;
const int INF = 1e8 + ;
const ll inf = 1e17 + ;
const db eps = 1e-;
const int MAXN = 2e5+1e3;
char pool[MAXN]; struct Str{
int st, len;
}str[MAXN];
struct state {
int len, pre, ch[];
};
struct SAM {
int sz, last;
state st[MAXN];
state& operator[] (int x) {
return st[x];
}
void clear(int x) {
CLR(st[x].ch);
}
void init() {
sz=, last=;
st[].len=, st[].pre=-;
clear();
}
void add(int c) {
int cur=sz++, p;
clear(cur);
st[cur].len=st[last].len+;
for(p=last; p!=-&&!st[p].ch[c]; p=st[p].pre)
st[p].ch[c]=cur;
if(p==-) st[cur].pre=;
else {
int q=st[p].ch[c];
if(st[q].len==st[p].len+)
st[cur].pre=q;
else {
int clone=sz++;
st[clone]=st[q];
st[clone].len=st[p].len+;
st[cur].pre=st[q].pre=clone;
for(; p!=-&&st[p].ch[c]==q; p=st[p].pre)
st[p].ch[c]=clone;
}
}
last=cur;
}
int find(string t) {//查询lcs
int now=, l=, ans=;
int len=t.length();
for (int i=; i<len; i++) {
while(now&&!st[now].ch[t[i]-'a']) {
now=st[now].pre;
l=st[now].len;
}
if(st[now].ch[t[i]-'a']) {
++l;
now=st[now].ch[t[i]-'a'];
}
ans=max(l, ans);
}
return ans;
}
} sam;
string a[maxn];
bool check(int sel, int n) {
for (int i=; i<n; i++) {
if (i!=sel) {
if (sam.find(a[i])!=a[i].length()) return ;
}
}
return true;
}
char ans[maxn];
void solve() {
int n; scanf("%d", &n);
str[].st=;
int sel=, maxx=;
for (int i=; i<n; i++) {
scanf("%s", pool);
int len=strlen(pool);
if (len>maxx) {
maxx=len;
sel=i;
}
a[i]=string(pool);
}
sam.init();
int len=a[sel].length();
for (int i=; i<len; i++)
sam.add(a[sel][i]-'a');
for (int i=; i<len; i++)
ans[i]=a[sel][i];
if(check(sel,n)) {
int l=a[sel].length();
for (int i=; i<len; i++)
printf("%c", ans[i]);
puts("");
}
else puts("No");
}
int main() {
int t = , cas = ;
//freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &t);
while(t--) {
// printf("Case %d: ", cas++);
solve();
}
return ;
}
hdu 6208(后缀自动机、或者AC自动机的更多相关文章
- hdu 4117 GRE Words (ac自动机 线段树 dp)
参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...
- HDU 3341 Lost's revenge AC自动机+dp
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- HDU 2457 DNA repair(AC自动机+DP)题解
题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...
- HDU 2222 Keywords Search(AC自动机)题解
题意:给你几个keywords,再给你一段文章,问你keywords出现了几次. 思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类 ...
- HDU - 6096 :String (AC自动机,已知前后缀,匹配单词,弱数据)
Bob has a dictionary with N words in it. Now there is a list of words in which the middle part of th ...
- HDU 2222 Keywords Search 【AC自动机】
题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=2222] 题意:给出很多小字符串,然后给出一个文本串,问文本串中包含多少个小字符串.也就是说如果文本串 ...
- HDU 5384 字典树、AC自动机
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5384 用字典树.AC自动机两种做法都可以做 #include<stdio.h> #includ ...
- HDU 2896 病毒侵袭(AC自动机)
病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2222 Keywords Search (AC自动机)
题意:给你一些模式串,再给你一串匹配串,问你在匹配串中出现了多少种模式串,模式串可以相同 AC自动机:trie树上进行KMP.首先模式串建立trie树,再求得失配指针(类似next数组),其作用就是在 ...
随机推荐
- java面试题:网络通信
网络分层 Q:OSI网络七层模型. Http Q:http协议的状态码有哪些?含义是什么? 200,服务器已成功处理了请求. 302,重定向. 400,错误请求. 401,未授权,请求要求身份验证. ...
- as3.0 在数组中找个找个,并且替换
var arr:Array=[1,2,7,9,3,5,6]; var findNum:Number =5//想要找到的数字 var replaceNum:Object =3//想要替换的数字 var ...
- switch只跟在这些之后
switch case 可以用在他们之后
- HDU_1024.MaxSumPlusPlus(基础DP + 滚动数组优化讲解)
这道题打破了我常规的做题思路,因为这是我刚开始训练DP,感觉这道题目好晕眼呀,emm其实就是感觉自己是真的菜...... 为什么说打破了我的做题思路呢,因为我平时看题解都是在已经AC或者完全不懂的情况 ...
- HDU-2612.Find way .(不同起点不同终点的BFS)
我要被这个好用的memset气死了...... 真香 #include <cstring> #include <string> int main () { ]; memset( ...
- TOJ3097: 单词后缀 (字典树 or map瞎搞)
传送门 (<---可以点击的~) 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte 描述 有些英语单词后缀都是一样的,现在我们需要从给定的一堆单词里 ...
- iOS 开发实用工具
史蒂芬的博客 (各种软件) http://www.sdifen.com/ 产品原型设计工具 -- 1.墨刀 2.Axure RP 检测接口工具 ---- 1.Charles 2. postman607 ...
- pyspider入门
1.http://www.pyspider.cn/jiaocheng/pyspider-webui-12.html 2.https://blog.csdn.net/weixin_37947156/ar ...
- 单元测试使用spring注解获取bean
在实际项目开发中经常会有单元测试,单元测试中经常会用类似这样的代码片段获取spring管理的bean @Test public void testSendEmail(){ MessageService ...
- hdu 4004 (二分加贪心) 青蛙过河
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4004 题目意思是青蛙要过河,现在给你河的宽度,河中石头的个数(青蛙要从石头上跳过河,这些石头都是在垂 ...