HDU 6208 The Dominator of Strings【AC自动机/kmp/Sunday算法】
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.
10
you
better
worse
richer
poorer
sickness
health
death
faithfulness
youbemyweddedwifebetterworsericherpoorersicknesshealthtilldeathdouspartandpledgeyoumyfaithfulness
5
abc
cde
abcde
abcde
bcde
3
aaaaa
aaaab
aaaac
#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算法】的更多相关文章
- HDU 6208 The Dominator of Strings 后缀自动机
The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java ...
- hdu 6208 The Dominator of Strings【AC自动机】
hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...
- HDU 6208 The Dominator of Strings(AC自动机)
The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java ...
- HDU - 6208 The Dominator of Strings HDU - 6208 AC自动机 || 后缀自动机
https://vjudge.net/problem/HDU-6208 首先可以知道最长那个串肯定是答案 然后,相当于用n - 1个模式串去匹配这个主串,看看有多少个能匹配. 普通kmp的话,每次都要 ...
- HDU 6208 The Dominator of Strings ——(青岛网络赛,AC自动机)
最长的才可能成为答案,那么除了最长的以外全部insert到自动机里,再拿最长的去match,如果match完以后cnt全被清空了,那么这个最长串就是答案.事实上方便起见这个最长串一起丢进去也无妨,而且 ...
- HDU 2222:Keywords Search(AC自动机模板)
http://acm.hdu.edu.cn/showproblem.php?pid=2222 KMP是单模式串匹配的算法,而AC自动机是用于多模式串匹配的算法.主要由Trie和KMP的思想构成. 题意 ...
- SPOJ 7758. Growing Strings AC自动机DP
Growing Strings 题目:给出n个字符串,问最多能够选出多少个串组成序列,并满足前一个字符串是后一个字符串的子串. 分析: AC自动机经典水题... 考虑每个节点结尾时,他能够选出最多的串 ...
- hdu_5507_GT and strings(AC自动机)
题目链接:hdu_5507_GT and strings 题意:给n个字符串和q个询问,每个询问给两个数字x,y,问1.x是否为y的子序列,2.x是否为y的子串,是输出1,否则输出0,每个询问输出2个 ...
- HDU 2457/POJ 3691 DNA repair AC自动机+DP
DNA repair Problem Description Biologists finally invent techniques of repairing DNA that contains ...
随机推荐
- NotifyIcon控件
NotifyIcon就是系统托盘控件.通知区域中的图标是一些进程的快捷方式,这些进程在计算机后台运行,如防病毒程序或音量控制.这些进程不会具有自己的用户界面.NotifyIcon 类提供了编写此功能的 ...
- BZOJ4563 HAOI2016放棋子(高精度)
没看清题还以为是要求数最大匹配数量……注意到任意障碍不在同一行同一列,且恰好有n个障碍,不妨通过交换列使得第i行第i列均有障碍.那么就是个错排了.居然wa了一发简直没救. #include<io ...
- [Leetcode] n queens ii n皇后问题
Follow up for N-Queens problem. Now, instead outputting board configurations, return the total numbe ...
- BZOJ3573 [Hnoi2014]米特运输 【贪心】
题目链接 BZOJ3573 题解 题目又臭又长系列 题意:修改尽量少的点权,使得: ①同个节点的所有儿子点权相同 ②任意非叶节点权值等于其儿子权值之和 容易发现一旦任意一个点权值确定,整棵树权值就确定 ...
- BZOJ2120 数颜色 【带修改莫队】
2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MB Submit: 6579 Solved: 2625 [Submit][Status][Discus ...
- RTL2832U+R820T电视棒windows下安装sdr# 以及搭建ADS-B使用VirtualRadar看飞机的教程
本文中提到的软件随后我会打包给出下载地址.这篇文章是我根据网上的教程和自己的经验修改的详细版本,为了方便入门新手.先来说说RTL2832U+R820T在windows下安装sdr#的方法.首先科普下s ...
- typescript的入门
命令行使用tsc 1.安装typescript npm install -g typescript 2.新建一个index.ts 输入export hello class{} 3.编译 tsc ind ...
- 解析json方式之net.sf.json
前面转载了json解析的技术:fastjson,今天说下另外一种技术. 下载地址 本次使用版本:http://sourceforge.net/projects/json-lib/files/json- ...
- Document base D:\devTools\apache-tomcat-6.0.51\webapps\AppService does not exist or is not a readable directory
tomcat通过eclipse发布项目到webapp后 手动删除在webapp目录下的文件,启动tomcat时,会报出异常找不到那个删除的项目. 解决方法是(1)重新发布项目到webapp (2)在 ...
- GTK+与MFC不完全对比
转载自:http://tech.ddvip.com/2007-11/119640973738229.html 1. 两者都是基于面向对象设计的.尽管MFC是用C++写的,而GTK+是用C写的,但思想都 ...