传送门: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. Spark内核解析

    Spark内核概述 Spark内核泛指Spark的核心运行机制,包括Spark核心组件的运行机制.Spark任务调度机制.Spark内存管理机制.Spark核心功能的运行原理等,熟练掌握Spark内核 ...

  2. 【剑指 Offer】06.从尾到头打印链表

    题目描述 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 限制: 0 <= 链表长度 <= 10 ...

  3. 关于spring-data与elasticsearch的使用,自定义repository

    之前没有使用过spring-data,关于spring-data有很多很棒的设计,例如仅仅只需要声明一个接口就行,你甚至都不需要去实现,spring-data有内置默认的实现类,基本就上完成绝大多数对 ...

  4. .NET 5网络操作的改进

    随着.net 5在11月的发布,现在是谈论网络栈中许多改进的好时机.这包括对HTTP.套接字.与网络相关的安全性和其他网络通信的改进.在这篇文章中,我将重点介绍一些版本中更有影响力和更有趣的变化. H ...

  5. kubernets与API服务器进行交互

    一  为何需要与kubernets集群的API服务器进行交互 1.1  kubernets提供了一种downapi的资源可以将pod的元数据渲染成环境变量或者downward卷的形式挂载到容器的文件系 ...

  6. kubernets之secret资源

    一  对于一些保密度比较高的文件,k8s又是如何存储的呢? 针对那些保密度比较高的配置文件,例如证书以及一些认证配置不能直接存储在configmap中,而是需要存储在另外一种资源中,需要对存储在里面的 ...

  7. Electron实用技巧-开机启动时隐藏主窗口,只显示系统托盘

    # 1 在桌面软件中,开机自启动是很常见的功能,在electron中也提供了很好的支持,以下是主要代码: //应用是否打包if (app.isPackaged) {  //设置开机启动  app.se ...

  8. SQLSERVER 修改数据实例的排序规则

    SQL Server服务器修改排序规则的方法 操作及验证步骤: 1 登录数据库后,查看当前安装数据库默认排序规则的两种方式 方式一.使用SQL Server 2014 Management Studi ...

  9. Spring-01-事务

    Spring事务机制 spring事务机制最重要的两个配置项,隔离级别和传播特性. 1. 隔离级别 隔离级别针对高并发问题导致的数据库丢失更新问题 1.1 数据库的4大基本特征 原子性(Atomic) ...

  10. ModuleNotFoundError 模块寻找路径

    t = os.path.dirname(os.path.dirname((os.path.dirname(os.path.abspath(__file__)))))os.path.sys.path.a ...