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 ...
随机推荐
- 认识webservice
1.为什么需要webservice? 目前还有很多商用程序继续在使用C++.Java.Visual Basic和其他各种各样的语言编写.现在,除了最简单的程序之外,所有的应用程序都需要与运行在其他异构 ...
- Java入门-jdk安装与环境搭建
计算机 计算机的组成:硬件+软件 1.硬件 1.1CPU 好比人的大脑 主要负责数据的运算以及控制 1.2内存 存储数据(临时存储) 缺点: 如果断电,数据丢失 如果程序关闭或退出,数据丢失 1.3硬 ...
- 【Flutter】容器类组件之Scaffold、TabBar、底部导航
前言 一个完整的路由页可能会包含导航栏.抽屉菜单(Drawer)以及底部Tab导航菜单等.Flutter Material组件库提供了一些现成的组件来减少开发任务.Scaffold是一个路由页的骨架, ...
- Flink源码剖析:Jar包任务提交流程
Flink基于用户程序生成JobGraph,提交到集群进行分布式部署运行.本篇从源码角度讲解一下Flink Jar包是如何被提交到集群的.(本文源码基于Flink 1.11.3) 1 Flink ru ...
- 基础练习(上) - 蓝桥杯(Python实现)
闰年判断: 题目: 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个年份,判断这一年是不是闰年. 当以下情况之一满足时,这一年是闰年: 1. 年份是4的倍数而不是100的倍数 ...
- [Noip模拟题]Seq
题目描述 由于hyf长得实在是太帅了,英俊潇洒,风流倜傥,人见人爱,花见花开,车见车载.有一群MM排队看hyf.每个MM都有自己独特的风格,由于hyf有着一颗包容的心,所以,什么风格的MM他都喜欢-- ...
- 解决Python内CvCapture视频文件格式不支持问题
解决Python内CvCapture视频文件格式不支持问题 在读取视频文件调用默认的摄像头cv.VideoCapture(0)会出现下面的视频格式问题 CvCapture_MSMF::initStre ...
- uni-app开发经验分享十四:小程序超过2M限制的方法——分包加载
起初小程序上线时,微信限制了代码包不能超过1MB,后来功能变大变成了2M了,限制大小是出于对小程序启动速度的考虑,希望用户在使用任何一款小程序时,都能获得一种"秒开"体验.但是 ...
- 它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程
[Linux编程]守护进程(daemon)详解与创建_mick_seu的博客-CSDN博客_linux daemon https://blog.csdn.net/woxiaohahaa/article ...
- functools.singledispatchmethod(Python 3.8) | 码农网 https://www.codercto.com/a/83245.html
functools.singledispatchmethod(Python 3.8) | 码农网 https://www.codercto.com/a/83245.html