传送门: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 (后缀数组)的更多相关文章

  1. POJ 1226 Substrings(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...

  2. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  3. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  4. POJ 3415 Common Substrings 后缀数组+并查集

    后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height   求完之后按height值从大往小合并.  height值代表的是  sa[i]和sa[i ...

  5. 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 ...

  6. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  7. POJ 2406 KMP/后缀数组

    题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...

  8. 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 ...

  9. UVALive - 6869 Repeated Substrings 后缀数组

    题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...

随机推荐

  1. 初识sa-token,一行代码搞定登录授权!

    前言 在java的世界里,有很多优秀的权限认证框架,如Apache Shiro.Spring Security 等等.这些框架背景强大,历史悠久,其生态也比较齐全. 但同时这些框架也并非十分完美,在前 ...

  2. Nginx集成Naxsi防火墙

    前言 因工作原因,接触到了WAF,今天部署了一下Naxsi,记录一下 GitHub 正文 环境 Centos 7 下载 更新yum yum update -y 安装必要依赖 yum install g ...

  3. Head First 设计模式 —— 11. 组合 (Composite) 模式

    思考题 我们不仅仅要支持多个菜单,升值还要支持菜单中的菜单.你如何处理这个新的设计需求? P355 [提示]在我们的新设计中,真正需要以下三点: P354 我们需要某种属性结构,可以容纳菜单.子菜单和 ...

  4. Java多线程-锁的区别与使用

    目录 锁类型 可中断锁 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 Synchronized与Static Synchron ...

  5. Openstack 启动一个实例(九)

    Openstack 启动一个实例(九) 创建一个提供者网络: # 创建一个提供者网络: openstack network create --share --external --provider-p ...

  6. 记录Js动态加载页面.append、html、appendChild、repend添加元素节点不生效以及解决办法

    今天再优化blog页面的时候添加了个关注按钮和图片,但是页面上这个按钮和图片时有时无,本来是搞后端的,被这个前端的小问题搞得抓耳挠腮的! 网上各种查询解决方案,把我解决问题的艰辛历程分享出来,希望大家 ...

  7. Netty学习:EventLoop事件机制

    目录 EventLoop是什么 EventLoop适用的场景 Netty中的EventLoop Netty中的大量inEventLoop判断 Netty是如何建立连接并监听端口的-NIOSocketC ...

  8. SAP 中session和外部断点设置的区别

    1 Session Breakpoints:只在当前user session的所有main session中有效 2 External Breakpoints 在abap editor或事务SICF中 ...

  9. 三十二:WEB漏洞-文件操作之文件下载读取全解

    文件下载读取 原路,检测,利用,修复 利用 数据库配置文件下载或者读取后续 接口密钥信息文件下载或者读取后续 文件名,参数值,目录符号 read.xxx?filename= down.xxx?file ...

  10. 计算机网络安全 —— 非对称加密算法 RSA 和数字签名(二)

    一.非对称加密算法基本概念 在对称密钥系统中,两个参与者要共享同一个秘密密钥.但怎样才能做到这一点呢?一种是事先约定,另一种是用信使来传送.在高度自动化的大型计算机网络中,用信使来传送密钥显然是不合适 ...