【POJ 1226】Substrings【后缀数组】
来源:互联网 发布:太原哪里购买知豆d3 编辑:程序博客网 时间:2024/05/29 19:00
题目:给出若干的字符串,求一个最长的串,使得这个串或者这个串的反转出现在这个若干个串中。求出这个串的长度。
题解:根据题意,我们可以这样考虑问题,将给出的字符串,我们都求一个反转。然后将反转的串和原串连接在一起。这样就相当于求一个最长的串,使得它出现在每一个我们构造的串中。
这样可以转化成后缀数组的问题,我们将每一个串以及它的反转用一个不出现的字符连接起来,然后把所有这样的串再用一个不出现的字符连接起来。这里注意每一个连接符都是要求不相同的。然后对这个大串跑一次后缀数组,我们记录每一个字符是属于第几个串的。接下来就是二分答案,通过二分串的长度len,我们对height[i]进行分组,对于每一组中的height都要大于等于len,然后计算这些height所代表的两个后缀是否是出现在开始给定的若干的字符串中,若都出现,则说明存在长度为len的字串满足要求。
#include <cstdio>#include <string.h>#define maxn 202010#include <iostream>using namespace std;int wwa[maxn],wwb[maxn],wwv[maxn],wws[maxn];//比较函数int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}//倍增算法void da(int *r,int *sufix,int n,int m){ int i,j,p,*x=wwa,*y=wwb,*t; for(i=0;i<m;i++) wws[i]=0; for(i=0;i<n;i++) wws[x[i]=r[i]]++; for(i=1;i<m;i++) wws[i]+=wws[i-1]; for(i=n-1;i>=0;i--) sufix[--wws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sufix[i]>=j) y[p++]=sufix[i]-j; for(i=0;i<n;i++) wwv[i]=x[y[i]]; for(i=0;i<m;i++) wws[i]=0; for(i=0;i<n;i++) wws[wwv[i]]++; for(i=1;i<m;i++) wws[i]+=wws[i-1]; for(i=n-1;i>=0;i--) sufix[--wws[wwv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sufix[0]]=0,i=1;i<n;i++) x[sufix[i]]=cmp(y,sufix[i-1],sufix[i],j)?p-1:p++; } return;}//保存初始字符串int r[maxn];//排名数组,公共长度数组,后缀数组int rank[maxn],height[maxn],sufix[maxn];//求height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公共前缀,//也就是排名相邻的两个后缀的最长公共前缀//有height[i]>=h[i-1]-1void calheight(int *r,int *sufix,int n){ int i,j,k=0;//记录排名 for(i=0;i<=n;i++) rank[sufix[i]]=i; //记录排名相邻的后缀的公共子串长度 for(i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sufix[rank[i]-1];r[i+k]==r[j+k];k++); return;}int belong[maxn], n;char w[120];bool vis[maxn];bool ch(int mid, int len) { int i, j, tot = 0; memset(vis, false, sizeof(vis)); for (i = 2;i <= len;i++) { if (height[i] < mid) { tot = 0; memset(vis, false, sizeof(vis)); }else { int id = belong[sufix[i]], idd = belong[sufix[i-1]]; if (!vis[id]) { vis[id] = true; tot++; } if (!vis[idd]) { vis[idd] = true; tot++; } if (tot == n) return true; } } return false;}int main() { int T, i, j; scanf("%d", &T); while (T--) { scanf("%d", &n); int len, m = 0, sp = 140; for (i = 1;i <= n;i++) { scanf("%s", w); len = strlen(w); for (j = 0;j < len;j++) { belong[m] = i; r[m++] = w[j]; } belong[m] = sp, r[m++] = sp++; for (j = len-1;j >= 0;j--) { belong[m] = i, r[m++] = w[j]; } belong[m] = sp, r[m++] = sp++; } r[m] = 0; da(r, sufix, m+1, sp); calheight(r, sufix, m); //puts("haha"); int f = 0, r = len, mid, ans = 0; while (f <= r) { mid = f+r>>1; if (ch(mid, m)) f = mid+1, ans = mid; else r = mid-1; } printf("%d\n", ans); }}
0 0
- POJ 1226 Substrings(后缀数组)
- POJ 1226 Substrings (后缀数组)
- 【POJ 1226】Substrings【后缀数组】
- POJ 1226 Substrings 后缀数组
- POJ 1226 Substrings (后缀数组)
- POJ-1226(后缀数组)(Substrings)
- POJ 1226 Substrings(后缀数组+二分)
- poj 1226 Substrings (后缀数组应用)
- poj 1226 Substrings (后缀数组)
- POJ-1226 Substrings(后缀数组)
- |poj 1226|后缀数组|二分|Substrings
- poj 1226 Substrings (二分+后缀数组)
- POJ 1226 Substrings KMP暴力 或 后缀数组
- poj 3415 Common Substrings 后缀数组
- poj Common Substrings(后缀数组&单调队列)
- 【后缀数组】 POJ 3415 Common Substrings
- poj 3415 Common Substrings (后缀数组应用)
- [POJ 3415]Common Substrings(后缀数组)
- 使SQL用户只能看到自己拥有权限的库
- 王健林电商梦为何会是一场噩梦?
- Myeclipse deBUG模式 鼠标悬停显示相关参数问题
- Linux计划任务及ntp服务
- Map元素的两种取出方式练习
- 【POJ 1226】Substrings【后缀数组】
- Java解析URL传输的数据
- 中国好声音3第一期学员背景扒皮
- imageView设置网址图片
- 在beaglebone上实现AM3359与FPGA的GPMC通信
- Android 之旅开始了!先自我了解下Android与Linux之间的关系
- 万达电商管理层又全换了一遍 这是什么节奏呢
- centos6.5下使用yum安装openfire
- exec函数