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. [洛谷P4208][JSOI2008]最小生成树计数

    题目大意:有$n$个点和$m$条边(最多有$10$条边边权相同),求最小生成树个数 题解:对于所有最小生成树,每种边权的边数是一样的.于是就可以求出每种边权在最小生成树中的个数,枚举这种边的边集,求出 ...

  2. MySQL事物机制具备四点:简称ACID操作

    MySQL事物机制具备四点:简称ACID操作 1.原子性:要么都做,要么都不做(两条数据(写入和存储)一步未成功,整体回滚) 2.一致性:数据库的状态改变(两条数据(写入和存储)均成功,符合原子性,但 ...

  3. MySQL使用笔记(一)安装配置

    By francis_hao    Nov 27,2016   一般软件的安装都是可以通过源码和安装包安装,源码安装可配置性好些,安装包安装比较省事,况且使用yum也可以解决依赖的问题,基本实现了一键 ...

  4. HDU 2126 01背包(求方案数)

    Buy the souvenirs Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  5. maven与gradle的对比

    Java世界中主要有三大构建工具:Ant.Maven和Gradle.经过几年的发展,Ant几乎销声匿迹.Maven也日薄西山,而Gradle的发展则如日中天.笔者有幸见证了Maven的没落和Gradl ...

  6. mysql修改表中某个字段的默认值

    Mysql中用SQL增加.删除字段,修改字段名.字段类型.注释,调整字段顺序总结   在网站重构中,通常会进行数据结构的修改,所以添加,删除,增加mysql表的字段是难免的,有时为了方便,还会增加修改 ...

  7. ios webapp调试神器MIHTool

    android平台有直接用chrome beta就可以调试,具体操作办法可以查看这篇教程<Android 设备 Chrome 远程调试>Mac的高富帅直接可以用safari提供“web检查 ...

  8. css实现九宫格图片自适应布局

    我之前写九宫格自适应布局的时候,每个格子是使用媒体查询器(@media)或者js动态设置css,根据不同的手机屏幕宽度,适配不同手机,但是这样有个很大的缺点,那就是移动端的屏幕尺寸太多了,就得写很多代 ...

  9. jsp中的一些细节和注意要点。。。。。简记

    一: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en&quo ...

  10. Vijos 1232 核电站问题

    核电站问题 描述 一个核电站有N个放核物质的坑,坑排列在一条直线上.如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 现在,请你计算:对于给定的N和M,求不发生爆炸的放置核物 ...