SPOJ - PHRASES Relevant Phrases of Annihilation
传送门:SPOJ - PHRASES(后缀数组+二分)
题意:给你n个字符串,找出一个最长的子串,他必须在每次字符串中都出现至少两次。
题解:被自己蠢哭...记录一下自己憨憨的操作,还一度质疑评测鸡(哭...
首先是多个字符串的常规操作(目前写的题少,见到的都是这样)连成一个字符串,中间用不同的且没出现过的字符隔开。然后后缀数组求出sa数组和height数组,二分子串长度,用mx数组记录该串中的这个子串的起点最大值,mi数组记录最小值,如果所有串中的mx-mi都>=k说明这个长度可以。
1 #include<cstdio>
2 #include<algorithm>
3 #include<queue>
4 #include<iostream>
5 #include<cmath>
6 #include<cstring>
7 using namespace std;
8
9 //sa:字典序中排第i位的起始位置在str中第sa[i] sa[1~n]为有效值
10
11 //rnk:就是str第i个位置的后缀是在字典序排第几 rnk[0~n-1]为有效值
12
13 //height:字典序排i和i-1的后缀的最长公共前缀 height[2~n]为有效值,第二个到最后一个
14
15 const int INF=0x3f3f3f3f;
16 const int maxn = 1e5+10;
17 int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
18 int rnk[maxn],height[maxn],be[maxn];
19 char s[maxn];
20 int r[maxn],n,len,mx[maxn],mi[maxn];
21
22 int cmp(int *r,int a,int b,int k)
23 {
24 return r[a]==r[b]&&r[a+k]==r[b+k];
25 }
26
27 void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
28 {
29 int i,j,p,*x=wa,*y=wb,*t;
30 for(i=0; i<m; i++) wsf[i]=0;
31 for(i=0; i<=n; i++) wsf[x[i]=r[i]]++;
32 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
33 for(i=n; i>=0; i--) sa[--wsf[x[i]]]=i;
34 p=1;
35 j=1;
36 for(; p<=n; j*=2,m=p){
37 for(p=0,i=n+1-j; i<=n; i++) y[p++]=i;
38 for(i=0; i<=n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
39 for(i=0; i<=n; i++) wv[i]=x[y[i]];
40 for(i=0; i<m; i++) wsf[i]=0;
41 for(i=0; i<=n; i++) wsf[wv[i]]++;
42 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
43 for(i=n; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
44 swap(x,y);
45 x[sa[0]]=0;
46 for(p=1,i=1; i<=n; i++)
47 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
48 }
49 }
50
51 void getheight(int *r,int n)//n为添加0后的总长
52 {
53 int i,j,k=0;
54 for(i=1; i<=n; i++) rnk[sa[i]]=i;
55 for(i=0; i<n; i++){
56 if(k)
57 k--;
58 else
59 k=0;
60 j=sa[rnk[i]-1];
61 while(r[i+k]==r[j+k])
62 k++;
63 height[rnk[i]]=k;
64 }
65 }
66
67 bool check(int k)
68 {
69 for(int j=0;j<n;j++) mx[j]=-INF,mi[j]=INF; //一开始忘记初始化
70 for(int i=2;i<=len;i++){
71 if(height[i]>=k){
72 mx[be[sa[i]]]=max(mx[be[sa[i]]],sa[i]);
73 mi[be[sa[i]]]=min(mi[be[sa[i]]],sa[i]);
74 mx[be[sa[i-1]]]=max(mx[be[sa[i-1]]],sa[i-1]);
75 mi[be[sa[i-1]]]=min(mi[be[sa[i-1]]],sa[i-1]); //没眼睛写成了sa[i]
76 }
77 else{
78 int j=0;
79 for(j=0;j<n;j++) mx[j]=-INF,mi[j]=INF;
80 mx[be[sa[i]]]=sa[i],mi[be[sa[i]]]=sa[i];
81 }
82 int j=0;
83 for(j=0;j<n;j++){
84 if(mx[j]-mi[j]<k) break;
85 }
86 if(j==n) return true;
87 }
88 return false;
89 }
90
91 int main()
92 {
93 ios::sync_with_stdio(false);
94 cin.tie(0);
95 cout.tie(0);
96 int t;
97 cin>>t;
98 while(t--){
99 cin>>n;
100 len=0;
101 for(int i=0;i<n;i++){
102 cin>>s+len;
103 int p=strlen(s+len);
104 for(int j=0;j<p;j++){
105 r[j+len]=s[j+len]-'a'+1;
106 be[len+j]=i;
107 }
108 len+=p;
109 if(i!=n-1){
110 be[len]=i;
111 r[len++]=i+100;
112 }
113 }
114 r[len]=0;
115 getsa(r,sa,len,200);
116 getheight(r,len);
117 int l=0,r=min(len,10000);
118 int ans=0;
119 while(l<=r){
120 int mid=l+r>>1;
121 if(check(mid)){
122 ans=mid;
123 l=mid+1;
124 }
125 else r=mid-1;
126 }
127 cout<<ans<<endl;
128 }
129 return 0;
130 }
SPOJ - PHRASES Relevant Phrases of Annihilation的更多相关文章
- SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串
题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags You ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
[题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组)
You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages ...
- 【SPOJ 220】 PHRASES - Relevant Phrases of Annihilation
[链接]h在这里写链接 [题意] 给你n(n<=10)个字符串. 每个字符串长度最大为1e4; 问你能不能找到一个子串. 使得这个子串,在每个字符串里面都不想交出 ...
- SPOJ - PHRASES Relevant Phrases of Annihilation (后缀数组)
You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages ...
- SPOJ PHRASES Relevant Phrases of Annihilation(后缀数组 + 二分)题解
题意: 给\(n\)个串,要你求出一个最长子串\(A\),\(A\)在每个字串至少都出现\(2\)次且不覆盖,问\(A\)最长长度是多少 思路: 后缀数组处理完之后,二分这个长度,可以\(O(n)\) ...
- POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)
多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...
- SPOJ - PHRASES K - Relevant Phrases of Annihilation
K - Relevant Phrases of Annihilation 题目大意:给你 n 个串,问你最长的在每个字符串中出现两次且不重叠的子串的长度. 思路:二分长度,然后将height分块,看是 ...
- 【SPOJ 220】Relevant Phrases of Annihilation
http://www.spoj.com/problems/PHRASES/ 求出后缀数组然后二分. 因为有多组数据,所以倍增求后缀数组时要特判是否越界. 二分答案时的判断要注意优化! 时间复杂度\(O ...
随机推荐
- C#扫盲篇(四):.NET Core 的异步编程-只讲干货(async,await,Task)
关于async,await,task的用法和解释这里就不要说明了,网上一查一大堆.至于为啥还要写这篇文章,主要是其他文章水分太多,不适合新手学习和理解.以下内容纯属个人理解,如果有误,请高手指正.本文 ...
- three.js canvas内场景生成图片 canvas生成图片
第一种最简单的方法: 1 threeBox.render();//重点 解决拿到图片后为黑色 2 3 let src=threeBox.renderer.domElement.toDataURL(); ...
- Petalinux和Vivado的安装
Petalinux和Vivado的安装 背景 我是搞软件的, FPGA这块不太了解.由于机缘巧合,最近有接触到这块的开发.所以先挖一坑. 先声明我不是专业搞这块的,所以对这块的内容理解可能会有偏差,以 ...
- 【Flutter】功能型组件之异步UI更新
前言 很多时候会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面:又比如想展示Stream(比如文件 ...
- LeetCode374 猜数字大小
我们正在玩一个猜数字游戏. 游戏规则如下:我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字.每次你猜错了,我会告诉你这个数字是大了还是小了.你调用一个预先定义好的接口 guess(int n ...
- 如何利用Intellij Idea搭建python编译运行环境 (转)
首先进入Intellij Idea的官方网站:点击打开链接 点击download,选择旗舰版进行下载.网上的破解教程很多,也可以注册一个学生账号拿到一年的免费试用权. 安装过程不再细说,第一次打开选择 ...
- Session、Cookie与Token
http协议是无状态协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到 ...
- 安装newman error:package exports for 'c:\nmp\node_modules\newman\node_module 解决办法
一.场景描述: 通过npm安装newman时,一直失败. 尝试了很多安装命令: npm install -g newman npm install -g newman --registry=http: ...
- JAVA获取当前文件路径this.getClass().getResource方法详细讲解
public class Test { public void run() { // TODO Auto-generated method stub System.out.println(" ...
- 对 js加密数据进行爬取和解密
对 js加密数据进行爬取和解密 分析: 爬取的数据是动态加载 并且我们进行了抓包工具的全局搜索,没有查找到结果 意味着:爬取的数据从服务端请求到的是加密的密文数据 页面每10s刷新一次,刷新后发现数据 ...