UVALive 7902 后缀自动机
来源:互联网 发布:蚂蚁信息源码 编辑:程序博客网 时间:2024/06/08 14:50
题意
给N个字符串,找出第一个字符串中最短的一个子串,使得这个子串不在其他所有的字符串中出现。
题解
对于这样一道题,没有现成的工具可以利用,但是既然涉及到了子串的问题,就可以考虑后缀自动机。后缀自动机可以用来找最长公共子串。对于这道题,我们想要利用后缀自动机,就是需要采取一些措施,使得这个问题转化为最长公共子串的问题。
我们可以把其他字符串拼接成一个字符串,需要注意的是要在中间加上一个分割字符,因为如果没有这个字符的话,那么很有可能这个字符串与下一个字符串拼接成一个新的字符串,从而对结果产生影响。
拼接成一个字符串以后,把这个字符串加到后缀自动机上,就可以寻找最长公共子串了,在寻找最长公共子串的过程中,如果发生了失配,那么就意味着存在一段子串,这段子串不在任何一个字符串中存在,而这个字符串的长度就是当前匹配的最长公共子串长度-1。(这个原因是显而易见的,因为匹配失败就意味着不存在这个字串在其他字符串中。)这时候我们就需要比较一下字典序,进行答案的记录。
最后输出记录的位置对应的字符串就可以了。
代码
#include<bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define LL long long#define INF 0x3f3f3f3f#define eps 1e-10#define MAXN 3000010using namespace std;const int N=250010;char first[N];char second[N];struct Node { int st,ed; Node() {} Node(int st,int ed):st(st),ed(ed) {} bool operator < (const Node b) const { int lena=(ed-st+1),lenb=(b.ed-b.st+1); if(lena==lenb) { UP(i,0,lena) { if(first[st+i]!=first[b.st+i]) { return first[st+i]<first[b.st+i]; } } return true; } return lena<lenb; }};Node ans;struct Suffix_Auto { static const int NODE=N<<1,C=27; int allc,last,par[NODE],len[NODE],trans[NODE][C]; int newNode() { int ret=++allc; MEM(trans[ret],0); return ret; } void init() { allc=0; last=newNode(); par[last]=len[last]=0; } void extend(int c) { int p=last,np=newNode(); len[np]=len[last]+1; for(; p&&!trans[p][c]; p=par[p]) trans[p][c]=np; if(!p) par[np]=1; else { int q=trans[p][c]; if(len[q]==len[p]+1) par[np]=q; else { int nq=++allc; par[nq]=par[q]; len[nq]=len[p]+1; memcpy(trans[nq],trans[q],C<<2); par[np]=par[q]=nq; for(trans[p][c]=nq,p=par[p]; p&&trans[p][c]==q; p=par[p]) trans[p][c]=nq; } } last=np; } void update(Node nd) { if(ans.st==-1) { ans=nd; } else if(nd<ans) { ans=nd; } } void find(const char *st) { int stlen=strlen(st); int u=1; int now=0; UP(i,0,stlen) { int x=st[i]-'a'; if(trans[u][x]) { u=trans[u][x]; now++; } else { W(u&&!trans[u][x]) { u=par[u]; now=len[u]; } if(u) { now++; u=trans[u][x]; } else { now=0; u=1; } Node newNd=Node(i-now,i); update(newNd); } } }};Suffix_Auto sa;int main() {// freopen("d://in.txt","r",stdin);// freopen("d://out1.txt","w",stdout); int ks=1; int t; scanf("%d",&t); W(t--) { sa.init(); int n; scanf("%d",&n); UP(i,0,n) { if(i==0) scanf("%s",first); else { scanf("%s",second); int len=strlen(second); UP(i,0,len) sa.extend(second[i]-'a'); sa.extend(26); } } ans.st=-1; sa.find(first); printf("Case #%d: ",ks++); if(ans.st==-1) { printf("Impossible\n"); } else { UP(i,ans.st,ans.ed+1) printf("%c",first[i]); puts(""); } }}
阅读全文
0 0
- UVALive 7902 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机)
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 后缀自动机
- 头条数据切换
- Win10安装Ubuntu双系统导致Win10时间有问题
- N皇后问题非递归求解
- Gemini Blueprint参考文档 第10章 与bundle一起工作
- 图的存储结构之邻接表(详解)
- UVALive 7902 后缀自动机
- Unity Time类简介及应用
- linux 下关于任务的命令
- 模式二(区间更新,单点查询)
- Qt————学习记录(四)
- 【逻辑推理系列】海盗分金模型分析
- 冒泡排序
- python中反射4种方法的基本使用
- Java排序算法以及算法改进总结(冒泡、选择、插入、归并、快速排序)