题意:给你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自动机的更多相关文章

  1. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  2. 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 ...

  3. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  4. HDU 2222 Keywords Search(AC自动机)题解

    题意:给你几个keywords,再给你一段文章,问你keywords出现了几次. 思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类 ...

  5. 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 ...

  6. HDU 2222 Keywords Search 【AC自动机】

    题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=2222] 题意:给出很多小字符串,然后给出一个文本串,问文本串中包含多少个小字符串.也就是说如果文本串 ...

  7. HDU 5384 字典树、AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5384 用字典树.AC自动机两种做法都可以做 #include<stdio.h> #includ ...

  8. HDU 2896 病毒侵袭(AC自动机)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. HDU 2222 Keywords Search (AC自动机)

    题意:给你一些模式串,再给你一串匹配串,问你在匹配串中出现了多少种模式串,模式串可以相同 AC自动机:trie树上进行KMP.首先模式串建立trie树,再求得失配指针(类似next数组),其作用就是在 ...

随机推荐

  1. inception+archery SQL审核平台

    关闭防火墙和selinux 宿主机安装mysql,创建archery数据库,并给所有权限,允许远程连接到该数据库 grant all privileges on *.* to 'root'@'%' i ...

  2. Vue之数据监听存在的问题

    Vue之数据监听 当数据监听的是列表时,数据发生改变,不会被监听到. // 用$set修改数组中的数组能够被监听 // app.$set(this.hobby, 0, "爱你哦") ...

  3. Codeforces Beta Round #67 (Div. 2)

    Codeforces Beta Round #67 (Div. 2) http://codeforces.com/contest/75 A #include<bits/stdc++.h> ...

  4. 【转】以太网最大帧和最小帧、MTU

    根据rfc894的说明,以太网封装IP数据包的最大长度是1500字节,也就是说以太网最大帧长应该是以太网首部加上1500,再加上7字节的前导同步码和1字节的帧开始定界符,具体就是:7字节前导同步码 + ...

  5. 实现mapper接口注入的两种方式,以及后台的使用区别

    1.使用模板方式: <!--使用模板类实现mybatis --> <bean id="sqlSession" class="org.mybatis.sp ...

  6. 我的第一个WCF程序

    写WCF,VS需要一管理员身份呢启动,否则服务无法访问. model层 using System; using System.Runtime.Serialization; namespace MyMo ...

  7. 服务器webapi集成极光推送学习笔记

    一路坎坷,坑死你!!!入坑需做好心理准备. 第一天: 其文档支持不给力,和微信的文档支持比起来能气死你,刚开始弄,看了一大堆东西,找不到头绪从哪里开始弄.只好找了一些文档,先了解了其基本原理,参考文章 ...

  8. Oracle_高级功能(10) 备份恢复

    备份与恢复Oracle数据库有三种标准的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入是一种逻辑备份,冷备份和热备份是物理备份.一.导出/导入(Export/Import)利 ...

  9. android如何判断控件的显示或者隐藏

    可以利用Android view getVisibility()的值来实现,具体如下: (1)0 -------- VISIBLE 可见(1)4 -------- INVISIBLE 不可见但是占用布 ...

  10. 解决loadrunner录制页面的乱码问题

    以下亲自验证了的:好用.     三步解决loadrunner录制页面的乱码问题 第一步:去lr 的vugen的Tools -> Recoding Options -> Advanced ...