题目链接$\newcommand{\LCP}{\mathrm{LCP}}\newcommand{\suf}{\mathrm{suf}}$

题意

给定 $n$ 个字符串 $s_1, s_2, \dots, s_n$,求只在 $s_1$ 中出现过的最短子串,若有多解,输出字典序最小的。

分析

为了方便, 称只在 $s_1$ 中出现过的子串为「特殊子串」,记「字符串 $s$ 是字符串 $t$ 的子串」作 $ s \sqsubseteq t$ 。

引理 1

若 $s'$ 是特殊子串,若字符串 $s$ 满足 $s \sqsubseteq s_1$ 且 $s' \sqsubseteq s$,那么 $s$ 也是特殊子串。

因此可二分答案。

问题化为: 判断是否存在长为 $x~(x \le |s_1|)$ 的特殊子串.

用后缀数组解决上述判定问题

  1. 将 $s_1, s_2, \dots, s_n$ 用 未在原串中出现过各不相同 的字符链接成一个长串 $s$ , 构造 $s$ 的后缀数组 $\suf_1, \suf_2, \dots, \suf_i, \dots$ 和 height 数组 $h_1, h_2, \dots, h_i, \dots$ .
  2. 寻找后缀数组中满足如下条件的连续段 $\suf_i, \suf_{i+1}, \dots, \suf_j, \dots, \suf_{i+k-1}$.
    1. $\suf_j$ 起始于 $s_1$ 中
    2. $|\suf_j \sqcap s_1| \ge x$
    3. $|\LCP(\suf_{j_1}, \suf_{j_2})| \ge x$, $\LCP(s, t)$ 指字符串 $s, t$ 的最长公共前缀 (Longest Common Prefix)
    4. $h_i<x$ 且 $h_{i+k}<x$

存在长为 $x$ 的特殊子串 $\Longleftrightarrow$ 存在上述连续段

Implementation

#include <bits/stdc++.h>
using namespace std; const int N=3e5+5;
char s[N];
int a[N];
int suf[N], suf2[N], rk[N], cnt[N], h[N]; void SA(int *s, int n, int m, int *suf, int *suf2, int *rk, int *cnt){
for(int i=0; i<m; i++)
cnt[i]=0;
for(int i=0; i<n; i++)
cnt[rk[i]=s[i]]++;
for(int i=1; i<m; i++)
cnt[i]+=cnt[i-1];
for(int i=n-1; i>=0; i--)
suf[--cnt[rk[i]]]=i; for(int len=1; len<n; len<<=1){
int tail=0;
for(int i=n-len; i<n; i++)
suf2[tail++]=i;
for(int i=0; i<n; i++)
if(suf[i]>=len) suf2[tail++]=suf[i]-len; for(int i=0; i<m; i++)
cnt[i]=0;
for(int i=0; i<n; i++)
cnt[rk[i]]++;
for(int i=1; i<m; i++)
cnt[i]+=cnt[i-1];
for(int i=n-1; i>=0; i--)
suf[--cnt[rk[suf2[i]]]]=suf2[i]; swap(suf2, rk);
auto same=[suf2, len](int i, int j){
return suf2[i]==suf2[j] && suf2[i+len]==suf2[j+len];
}; rk[suf[0]]=0;
for(int i=1; i<n; i++)
rk[suf[i]]=rk[suf[i-1]]+!same(suf[i], suf[i-1]); m=rk[suf[n-1]]+1;
if(m==n) break;
}
} void calc(int *a, int *suf, int n, int *rk, int *h){
for(int i=0; i<n; i++)
rk[suf[i]]=i; for(int i=0, lcp=0; i<n-1; i++){
if(lcp) --lcp;
for(int j=suf[rk[i]-1]; a[j+lcp]==a[i+lcp]; lcp++);
h[rk[i]]=lcp;
}
} int ok(int x, int len0, int len, int *h){
//two-pointers
for(int i=1; i<=len; i++){ //tricky
if(suf[i]<len0 && suf[i]+x <= len0 && h[i]<x){ //error-prone
for(++i; i<=len && h[i]>=x && suf[i]<len0; i++);
if(i>len || h[i]<x){
assert(suf[i-1]>=0);
return suf[i-1];
}
}
}
return -1;
} int main(){
int T;
cin>>T; for(int cas=1; cas<=T; cas++){
printf("Case #%d: ", cas);
int n;
cin>>n;
cin>>s;
int len0=strlen(s), len=len0; for(int i=1; i<n; i++){
s[len++]='#';
cin>>(s+len);
len+=strlen(s+len);
} int m=256; for(int i=0; i<=len; i++){
if(s[i]=='#') a[i]=m++;
else a[i]=s[i];
} SA(a, len+1, m, suf, suf2, rk, cnt);
calc(a, suf, len+1, rk, h); int l=0, r=len0+1, res=-1;
for(; l+1<r; ){
int mid=(l+r)>>1;
int tmp=ok(mid, len0, len, h);
if(tmp!=-1){
res=tmp;
r=mid;
}
else l=mid;
} if(r>len0) puts("Impossible");
else{
for(int i=res; i<res+r; i++)
putchar(s[i]);
puts("");
}
} return 0;
}

2016 ACM-ICPC China Finals #F Mr. Panda and Fantastic Beasts的更多相关文章

  1. UVAL 7902 2016ECfinal F - Mr. Panda and Fantastic Beasts

    题意: 给出n个串,求一个最短的第一个串的子串使它不在其他的n-1个串中出现,若有多个求字典序最小的. Limits: • 1 ≤ T ≤ 42. • 2 ≤ N ≤ 50000. • N ≤ S1 ...

  2. 2016EC Final F.Mr. Panda and Fantastic Beasts

    题目大意 \(T(1\leq T\leq42)\)组数据,给定\(n(2\leq n\leq 50000)\)个字符串\(S_{i}(n\leq\sum_{i=1}^{n}S_{i}\leq 2500 ...

  3. [acm/icpc2016ChinaFinal][CodeforcesGym101194] Mr. Panda and Fantastic Beasts

    地址:http://codeforces.com/gym/101194 题目:略 思路: 这题做法挺多的,可以sam也可以后缀数组,我用sam做的. 1.我自己yy的思路(瞎bb的) 把第一个串建立s ...

  4. Gym 101194F Mr. Panda and Fantastic Beasts

    #include<bits/stdc++.h> using namespace std; #define ms(arr,a) memset(arr,a,sizeof arr) #defin ...

  5. 2016 ACM/ICPC Asia Regional Dalian Online 1006 /HDU 5873

    Football Games Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  6. ACM - ICPC World Finals 2013 C Surely You Congest

    原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 试题来源 ACM/ICPC World Fin ...

  7. HDU 5874 Friends and Enemies 【构造】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Friends and Enemies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  8. HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  9. HDU 5875 Function 【倍增】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Function Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

随机推荐

  1. dialog样式的activity设置activity的title为隐藏属性

    View view= this.findViewById(android.R.id.title);view.setVisibility(View.GONE);

  2. uvm_sequence_item——sequence机制(一)

    让子弹飞一会 UVM框架,将验证平台和激励分开,env以下属于平台部分,test和sequence属于激励,这样各司其职.我们可以将sequence_item 比喻成子弹,sequencer 类比成弹 ...

  3. Android学习总结(十八) ———— SQLite数据库使用

    一.基本概念 数据库最经典的四个操作 添加.删除.修改.查找,在处理大量数据的时候使用数据库可以帮我们迅速定位当前须要处理的数据,举个例子 好比现在要实现一个搜索功能 用数据库的话只须要其中一个搜索条 ...

  4. 洛谷 P2353 背单词

    题目背景 小明对英语一窍不通,令老师十分头疼.于是期末考试前夕,小明被逼着开始背单词…… 题目描述 老师给了小明一篇长度为N的英语文章,然后让小明背M个单词.为了确保小明不会在背单词时睡着,老师会向他 ...

  5. 推荐一个markdown格式转html格式的开源JavaScript库

    这个markdown格式转html格式的开源JavaScript库在github上的地址: https://github.com/millerblack/markdown-js 从markdown 格 ...

  6. mvc的model验证,ajaxhelper,验证机制语法

    ajaxhelper: onsuccess是调用成功后显示方法,还有一个方法是调用前显示 model验证: 控件前端验证: 需要引入的JS 其中第二个是ajaxhelper的必须验证 后台的两个同名不 ...

  7. 使用memcached缓存 替代solr中的LRUCache缓存

    前沿 在搜索引擎中,缓存被当做是不可缺少的部分,但是很多情况下,将缓存的实现过度依赖于分发服务器及webserver会很大程度上加重webserver 的负担,具体表现就是经常性的假死,拒绝服务,因此 ...

  8. 集成iAd广告

    在iPhone程序中集成广告,管他能不能赚钱,不放上一个iAd就心有不甘. 参考了下面这篇文章: http://bees4honey.com/blog/tutorial/how-to-add-iad- ...

  9. python之路——递归函数

    阅读目录 楔子 初识递归 再谈递归 递归函数与三级菜单 递归函数与二分查找算法 楔子 在讲今天的内容之前,我们先来讲一个故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢?从前 ...

  10. 7.逻辑运算 and or not

    1)优先级 ()> not  > and > o r and:真真为真,真假为假 ,假假为假 or:真真为真,真假为真,假假为假 print(2 > 1 and 1 < ...