Problem Description
Here you have a set of strings. A dominator is a string of the set dominating all strings else. The string S is dominated by T if S is a substring of T .
 
Input
The input contains several test cases and the first line provides the total number of cases.
For each test case, the first line contains an integer N

indicating the size of the set.
Each of the following N

lines describes a string of the set in lowercase.
The total length of strings in each case has the limit of 100000

.
The limit is 30MB for the input file.

 
Output
For each test case, output a dominator if exist, or No if not.
 
Sample Input
3
10
you
better
worse
richer
poorer
sickness
health
death
faithfulness
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
5
abc
cde
abcde
abcde
bcde
3
aaaaa
aaaab
aaaac
 
Sample Output
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
abcde
No
 
Source
 
【题意】:给n个串,问是否有一个串,包含了其他所有串。
【分析】:显然若这样的字符串存在就一定是最长的那个,然后考虑下AC自动机的入门题HDU2222,然后思路就清晰了,首先构建自动机,然后选出长度最长的一串来跑一遍自动机,统计所有字符串出现的个数,不重复统计,然后个数!=n就是No。
【代码*3】:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<string>
#include<iostream>
#define maxlen 100005
using namespace std;
int n;
int nxt[maxlen][],FAIL[maxlen],edd[maxlen],root,L;//nxt记录节点,在这里edd指针代表以当前节点为字符串尾的字符串个数
int mark[maxlen];
int newnode()
{
for(int i=;i<;i++)
nxt[L][i]=-;//节点连接的边初始化为-1
edd[L]=;
mark[L]=;
return L++;
}
void init()
{
L=;
root=newnode();
} void insert(char buf[],int l)//trie树的建立
{
int now=root;
for(int i=;i<l;i++)
{
if(nxt[now][buf[i]-'a']==-)nxt[now][buf[i]-'a']=newnode();
now=nxt[now][buf[i]-'a'];
}
edd[now]++;
}
void build()//建立ac自动机
{
queue<int>que;
for(int i=;i<;i++)
{
if(nxt[root][i]==-)nxt[root][i]=root;
else //若有连边则将节点加入队列 ,并将FAIL指针指向root
{
FAIL[nxt[root][i]]=root;
que.push(nxt[root][i]);
}
}
while(!que.empty())
{
int now=que.front();
que.pop();
for(int i=;i<;i++)
{
if(nxt[now][i]==-) //若无连边,则将该边指向当前节点FAIL指针指向的相应字符连接的节点
nxt[now][i]=nxt[FAIL[now]][i];
else //若有连边,则将儿子节点的FAIL指针指向当前节点FAIL指针指向相应字符接的节点
{
FAIL[nxt[now][i]]=nxt[FAIL[now]][i];
que.push(nxt[now][i]); //加入队列继续遍历
}
}
}
}
int query(char buf[],int l)
{
int now=root;
int res=;
for(int i=;i<l;i++)
{
now=nxt[now][buf[i]-'a'];
int temp=now;
while(temp!=root&&mark[temp]==)//根据题目要求改变形式
{
res+=edd[temp];
edd[temp]=;
mark[temp]=;
temp=FAIL[temp];
}
}
return res; //在这里返回的是匹配到的模式串的数量
}
char buf[maxlen],ans[maxlen];
string A[maxlen];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
int ma=;
for(int i=;i<n;i++)
{
scanf("%s",buf);
int l=strlen(buf);
if(ma<l)
{
ma=l;
strcpy(ans,buf);
}
insert(buf,l);
}
build();
int sum=query(ans,ma);
if(sum==n) puts(ans);
else puts("No");
}
}

AC自动机

#include <stdio.h>
#include <string.h>
char S[];
char *t[],*s;
int f[];
void getfail(char p[],int f[]) //字符串p自我匹配
{
int len=strlen(p);
f[]=f[]=;
for(int i=;i<len;i++)
{
int j=f[i];
while(j&&p[i]!=p[j])
j=f[j];
if(p[i]==p[j])
f[i+]=j+;//多匹配到了一个字符
else
f[i+]=;//该字符配不上
}
}
int find(char* T, char*P, int*f)//p去匹配字符串T
{
int n = strlen(T), m = strlen(P);
getfail(P, f); //得出部分匹配表
int j = ; //短串的下标
for(int i = ; i < n; i++) //长串下标
{
while(j && P[j] != T[i])//突然失配了
{
j = f[j]; //j往回退,直到0或者上一个字符相等的位置
}
if(P[j] == T[i])
{
j++; //匹配了一个字符,j++
}
if(j == m) //短串匹配到头了
{
return ;//i - m + 1;//返回成功匹配的起点字符位置
}
}
return -;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int maxlen=;
int p=;//记录最长串
s=S;
for(int i=;i<=n;i++)
{
scanf("%s",s);
t[i]=s;
if(strlen(s)>maxlen){
maxlen=strlen(s);
p=i;
}
s+=strlen(s)+;
}
int ans=;
for(int i=;i<=n;i++)
{
if(find(t[p],t[i],f)==)
ans++;
else break;
}
if(ans==n)
{
printf("%s\n",t[p]);
}
else puts("No");
}
return ;
}

KMP

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std; int f[];
int T,n;
char s[];
char *t[]; void getfail(char p[]) //字符串p自我匹配
{
int len=strlen(p);
f[]=f[]=;
for(int i=;i<len;i++)
{
int j=f[i];
while(j&&p[i]!=p[j])
j=f[j];
if(p[i]==p[j])
f[i+]=j+;//多匹配到了一个字符
else
f[i+]=;//该字符配不上
}
}
int find(char* T, char*P)//p去匹配字符串T
{
int n = strlen(T), m = strlen(P);
getfail(P); //得出部分匹配表
int j = ; //短串的下标
for(int i = ; i < n; i++) //长串下标
{
while(j && P[j] != T[i])//突然失配了
{
j = f[j]; //j往回退,直到0或者上一个字符相等的位置
}
if(P[j] == T[i])
{
j++; //匹配了一个字符,j++
}
if(j == m) //短串匹配到头了
{
return ;//i - m + 1;//返回成功匹配的起点字符位置
}
}
return -;
} int main(){ int max_len;
scanf("%d",&T); while(T--){
scanf("%d",&n);
max_len=;
int tmp;
char *qw;
char *io=s;
for(int i= ;i <= n;i++){
scanf("%s",io);
tmp=strlen(io);
if( tmp > max_len ){
max_len=tmp;
qw=io;
}
t[i]=io;
io+=strlen(io)+;
} int flag=; for(int j=;j<=n;j++){ if( find(qw,t[j]) != ){
flag=;
break ;
}
} if(flag){
printf("%s\n",qw);
}
else{
printf("No\n");
} } return ;
}

another KMP

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<vector>
using namespace std; typedef long long int LL; int Sunday(string text, string pattern){
int i = , j = , k;
int m = pattern.size(); if(pattern.size() <= || text.size() <= )
return -; for(; i<text.size();) {
if(text[i] != pattern[j]) {
for(k=pattern.size() - ; k>=; k--) {
if(pattern[k] == text[m])
break;
}
i = m-k;
j = ;
m = i+pattern.size();
}
else {
if(j == pattern.size()-)
return i-j;
i++;
j++;
} }
return -;
} vector<string> v; int main()
{
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
v.clear();
string t,text;
for(int i=;i<n;i++)
{
cin>>t;
if(text.length()<t.length())
text=t;
v.push_back(t);
}
int f=;
for(int i=;i<n;i++)
{
if(Sunday(text,v[i])== -)
{
f=;
break;
}
}
if(f)
cout<<text<<endl;
else
cout<<"No"<<endl;
}
return ;
}

Sunday algorithm

HDU 6208 The Dominator of Strings【AC自动机/kmp/Sunday算法】的更多相关文章

  1. HDU 6208 The Dominator of Strings 后缀自动机

    The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java ...

  2. hdu 6208 The Dominator of Strings【AC自动机】

    hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...

  3. HDU 6208 The Dominator of Strings(AC自动机)

    The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java ...

  4. HDU - 6208 The Dominator of Strings HDU - 6208 AC自动机 || 后缀自动机

    https://vjudge.net/problem/HDU-6208 首先可以知道最长那个串肯定是答案 然后,相当于用n - 1个模式串去匹配这个主串,看看有多少个能匹配. 普通kmp的话,每次都要 ...

  5. HDU 6208 The Dominator of Strings ——(青岛网络赛,AC自动机)

    最长的才可能成为答案,那么除了最长的以外全部insert到自动机里,再拿最长的去match,如果match完以后cnt全被清空了,那么这个最长串就是答案.事实上方便起见这个最长串一起丢进去也无妨,而且 ...

  6. HDU 2222:Keywords Search(AC自动机模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2222 KMP是单模式串匹配的算法,而AC自动机是用于多模式串匹配的算法.主要由Trie和KMP的思想构成. 题意 ...

  7. SPOJ 7758. Growing Strings AC自动机DP

    Growing Strings 题目:给出n个字符串,问最多能够选出多少个串组成序列,并满足前一个字符串是后一个字符串的子串. 分析: AC自动机经典水题... 考虑每个节点结尾时,他能够选出最多的串 ...

  8. hdu_5507_GT and strings(AC自动机)

    题目链接:hdu_5507_GT and strings 题意:给n个字符串和q个询问,每个询问给两个数字x,y,问1.x是否为y的子序列,2.x是否为y的子串,是输出1,否则输出0,每个询问输出2个 ...

  9. HDU 2457/POJ 3691 DNA repair AC自动机+DP

    DNA repair Problem Description   Biologists finally invent techniques of repairing DNA that contains ...

随机推荐

  1. [bzoj4071] [Apio2015]巴邻旁之桥

    Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...

  2. [UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)

    题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成.输出每次操作的$P_ ...

  3. 在C/C++函数中使用可变参数

    原文链接地址:http://blog.csdn.net/djinglan/article/details/8425768 下面介绍在C/C++里面使用的可变参数函数. 先说明可变参数是什么,先回顾一下 ...

  4. Kafka自我学习1-Multi-broker cluster

    ====================================Testing environment =========================================== ...

  5. npm获取配置值的两种方式

    命令行标记 在命令行上放置--foo bar设置foo配置参数为bar. 一个 -- 参数(argument)告诉cli解析器停止读取flags.一个 在命令行结尾的--flag参数(paramete ...

  6. js介绍自己的例子

    js并不是真正面向对象的语言,但是我们通过一些方法也是可以实现js的一些面向对象设计的.常见的构造函数有很多模式有构造函数模式,原型链,工厂模式等等.但就是因为,我初学者看起来非常吃力,理解起来都是很 ...

  7. 九大排序算法Java实现

    之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...

  8. 修改nginx对http请求数据大小限制

    1. 问题发现 在公司搭建了一个基于mindoc的wiki知识库,用nginx做的反向代理服务器,同事在使用过程中上传某个文件一直失败,于是看着看下mindoc自己的日志文件,发现都是类似于fastd ...

  9. 【Foreign】石子游戏 [博弈论]

    石子游戏 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output 输出T行,表示每组的答案. Sample Input 3 ...

  10. loj6030 「雅礼集训 2017 Day1」矩阵

    传送门:https://loj.ac/problem/6030 [题解] 以下把白称为0,黑称为1. 发现只有全空才是无解,否则考虑构造. 每一列,只要有0的格子都需要被赋值1次,所以设有x列有含有0 ...