传送门: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. Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类

    目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...

  2. nginx日志详细说明

    Nginx日志主要分为两种:访问日志和错误日志.日志开关在Nginx配置文件(/etc/nginx/nginx.conf)中设置,两种日志都可以选择性关闭,默认都是打开的. 访问日志 访问日志主要记录 ...

  3. libnum报错问题解决

    之前在使用python libnum库时报错 附上报错内容 Traceback (most recent call last) : File" D:/python file/ctf/RSA共 ...

  4. windows下如何安装Python、pandas

    windows下如何安装Python.pandas 本篇主要涵盖以下三部分内容: Python.Pycharm的安装 使用Pycharm创建.运行Python程序 安装pandas 1.Python. ...

  5. IE浏览器直接在页面中显示7z文件而不是下载问题解决

    IE浏览器中输入7z文件的完整下载URL后,不是保存文件,而是直接在页面中显示(当然是乱码) 这是因为浏览器对不同的资源文件处理的方式不同,例如图片文件,一般会直接打开,所以我们可以不用7z,使用zi ...

  6. Python赋值、浅复制和深复制

    Python赋值.浅复制和深复制 ​ 首先我们需要知道赋值和浅复制的区别: 赋值和浅复制的区别 赋值,当一个对象赋值给另一个新的变量时,赋的其实是该对象在栈中的地址,该地址指向堆中的数据.即赋值后,两 ...

  7. (06)-Python3之--判断、循环

    1.判断(if) 语法: if 条件(True/False): 条件为真时,执行的代码(要干的事情)[elif 条件: 条件为真时,执行的代码(要干的事情)elif 条件: 条件为真时,执行的代码(要 ...

  8. VMware vSphere (EXSI) 安装使用

    VMware vSphere 镜像下载 VMware vSphere Hypervisor (ESXi) 6.7 https://my.vmware.com/cn/web/vmware/downloa ...

  9. 两个list<Map<String,String>>放入一个list中

    // public static void main(String[] args) {// List<Map<String, String>> list2 = new Arra ...

  10. 函数式编程 偏函数 生成器 yield

    高阶函数 # 高阶函数def f(x): return x * x# map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Ite ...