POJ - 1226 Substrings (后缀数组)
传送门:POJ - 1226
这个题跟POJ - 3294 和POJ - 3450 都是一样的思路,一种题型。
POJ - 3294的题解可以见:https://www.cnblogs.com/lilibuxiangtle/p/12649853.html
题意:给你n个字符串,求最长子串的长度,要求子串或子串的翻转串在n个字符串中都出现。
题解:把每个字符串和字符串的翻转串连接起来,中间用不同且没出现过的字符隔开,然后再把n个字符串和翻转的串连到一起。然后后缀数组求出sa数组和height数组,用be数组标记每个位置的字符在哪个串中。二分长度,vis数组标记符合条件的串,cnt记录个数,如果cnt>=n则说明该长度可以,反之则不行。(重点!!vis及时标记 我憨憨的wa了好几发,找了快三个小时)
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];
19 char s[maxn];
20 int r[maxn],n,L;
21 int be[maxn],vis[110];
22
23 int cmp(int *r,int a,int b,int k)
24 {
25 return r[a]==r[b]&&r[a+k]==r[b+k];
26 }
27
28 void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
29 {
30 int i,j,p,*x=wa,*y=wb,*t;
31 for(i=0; i<m; i++) wsf[i]=0;
32 for(i=0; i<=n; i++) wsf[x[i]=r[i]]++;
33 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
34 for(i=n; i>=0; i--) sa[--wsf[x[i]]]=i;
35 p=1;
36 j=1;
37 for(; p<=n; j*=2,m=p){
38 for(p=0,i=n+1-j; i<=n; i++) y[p++]=i;
39 for(i=0; i<=n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
40 for(i=0; i<=n; i++) wv[i]=x[y[i]];
41 for(i=0; i<m; i++) wsf[i]=0;
42 for(i=0; i<=n; i++) wsf[wv[i]]++;
43 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
44 for(i=n; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
45 swap(x,y);
46 x[sa[0]]=0;
47 for(p=1,i=1; i<=n; i++)
48 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
49 }
50 }
51
52 void getheight(int *r,int n)//n为添加0后的总长
53 {
54 int i,j,k=0;
55 for(i=1; i<=n; i++) rnk[sa[i]]=i;
56 for(i=0; i<n; i++){
57 if(k)
58 k--;
59 else
60 k=0;
61 j=sa[rnk[i]-1];
62 while(r[i+k]==r[j+k])
63 k++;
64 height[rnk[i]]=k;
65 }
66 }
67
68 bool check(int k)
69 {
70 memset(vis,0,sizeof(vis));
71 int cnt=0;
72 for(int i=2;i<=L;i++){
73 if(height[i]>=k){
74 if(!vis[be[sa[i]]]) cnt++;
75 vis[be[sa[i]]]=1; //就是这个地方卡了我快3个小时!!!
76 if(!vis[be[sa[i-1]]]) cnt++;
77 vis[be[sa[i-1]]]=1;
78 }
79 else {
80 memset(vis,0,sizeof(vis));
81 cnt=0;
82 }
83 if(cnt>=n) return 1;
84 }
85 return 0;
86 }
87
88 int main()
89 {
90 ios::sync_with_stdio(false);
91 cin.tie(0);
92 cout.tie(0);
93 int t;
94 cin>>t;
95 while(t--){
96 cin>>n;
97 L=0;
98 for(int i=0;i<n;i++){
99 cin>>s;
100 int len=strlen(s);
101 for(int j=0;j<len;j++){
102 r[L]=s[j];
103 be[L++]=i;
104 }
105 r[L]=i+200;
106 be[L++]=i;
107 for(int j=len-1;j>=0;j--){
108 r[L]=s[j];
109 be[L++]=i;
110 }
111 if(i!=n-1) r[L]=i+n+200,be[L++]=i;
112 }
113 if(n==1) {
114 cout<<strlen(s)<<endl;
115 continue;
116 }
117 r[L]=0;
118 getsa(r,sa,L,500);
119 getheight(r,L);
120 int l=0,r=105,ans=0;
121 while(l<=r){
122 int mid=l+r>>1;
123 if(check(mid)) ans=mid,l=mid+1;
124 else r=mid-1;
125 }
126 cout<<ans<<endl;
127 }
128 return 0;
129 }
POJ - 1226 Substrings (后缀数组)的更多相关文章
- POJ 1226 Substrings(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- POJ - 3415 Common Substrings (后缀数组)
A substring of a string T is defined as: T( i, k)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|. Given two s ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- POJ 2406 KMP/后缀数组
题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...
- Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)
The repetition number of a string is defined as the maximum number \(R\) such that the string can be ...
- UVALive - 6869 Repeated Substrings 后缀数组
题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...
随机推荐
- LeetCode662 二叉树最大宽度
给定一个二叉树,编写一个函数来获取这个树的最大宽度.树的宽度是所有层中的最大宽度.这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空. 每一层的宽度被定义为两个端点(该层 ...
- 一条查询SQl是怎样执行的
MySQL的逻辑架构图 大体来说,MySQL可以分为Server层和存储引擎层两部分. Server层包括连接器.查询缓存.分析器,优化器等,涵盖MySQL的大多核心服务功能,以及所有的内置函数,存储 ...
- MySQL 设置保留几天的binlog
1 ) 查看默认的日志保存天数: mysql> show variables like 'expire_logs_days'; +------------------+-------+ | Va ...
- Linux监控工具vmstat命令
当linux服务器的发生告警,我们要查看当前系统的状态值,包括CPU使用率,内存使用情况,虚拟内存交换情况,IO读写情况等. top与vmstat这两个监控工具都满足要求,当然top还可以看到各个进程 ...
- MyBatis初级实战之四:druid多数据源
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 每月一更的《HelloGitHub》第 58 期,来啦!
HelloGitHub 分享 GitHub 上有趣.入门级的开源项目.欢迎大家: 贡献代码 宣传你觉得优秀的项目 Star 项目️ 本月刊是每月 28 号更新,再见月刊就是年后了.在这里提前祝大家:新 ...
- Windows Server 2012 R2 英文版汉化安装中文语言包教程更改为中文版
是这样的,一台海外的windows机器默认是英文版的,但是特别费劲用起来,就更改为中文版,因为海外的供应商并不提供中文版镜像. 1.首先打开控制面板,找到add language,拉到底就是有中文,很 ...
- 报错:java.lang.ClassNotFoundException: io.opentracing.util.GlobalTracer
报错:java.lang.ClassNotFoundException: io.opentracing.util.GlobalTracer 近来在做一个在线教育的项目,课程信息放在数据库,而视频放在阿 ...
- 容器调度 • Docker网络 • 持续交付 • 动态运行应用程序 部署的多元化
<英雄联盟>在线服务运维之道 - InfoQ https://www.infoq.cn/article/running-online-services-riot/ 第一章 简 介 我是Jo ...
- OSS与文件系统的对比 文件存储 块存储 对象存储
基本概念介绍_开发指南_对象存储 OSS-阿里云 https://help.aliyun.com/document_detail/31827.html 强一致性 Object 操作在 OSS 上具有 ...