博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【poj1226-出现或反转后出现在每个串的最长公共子串】后缀数组
阅读量:5081 次
发布时间:2019-06-13

本文共 3925 字,大约阅读时间需要 13 分钟。

题意:求n个串的最长公共子串,子串出现在一个串中可以是它的反转串出现。总长<=10^4.

题解:

对于每个串,把反转串也连进去。

二分长度,分组,判断每个组。

 

1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int N=2*21000; 8 int n,sl,cl,c[N],rk[N],sa[N],Rs[N],wr[N],y[N],h[N],st[N],ed[N],fst[N],fed[N]; 9 char s[N]; 10 bool vis[N]; 11 12 void get_sa(int m) 13 { 14 for(int i=1;i<=cl;i++) rk[i]=c[i]; 15 for(int i=1;i<=m;i++) Rs[i]=0; 16 for(int i=1;i<=cl;i++) Rs[rk[i]]++; 17 for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1]; 18 for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i; 19 20 int ln=1,p=0; 21 while(p
ln) y[++k]=sa[i]-ln; 26 27 for(int i=1;i<=cl;i++) wr[i]=rk[y[i]]; 28 for(int i=1;i<=m;i++) Rs[i]=0; 29 for(int i=1;i<=cl;i++) Rs[wr[i]]++; 30 for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1]; 31 for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i]; 32 33 for(int i=1;i<=cl;i++) wr[i]=rk[i]; 34 for(int i=cl+1;i<=cl+ln;i++) wr[i]=0; 35 p=1;rk[sa[1]]=1; 36 for(int i=2;i<=cl;i++) 37 { 38 if(wr[sa[i]]!=wr[sa[i-1]] || wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++; 39 rk[sa[i]]=p; 40 } 41 ln*=2,m=p; 42 } 43 sa[0]=0,rk[0]=0; 44 } 45 46 void get_h() 47 { 48 int k=0,j; 49 for(int i=1;i<=cl;i++) if(rk[i]!=1) 50 { 51 j=sa[rk[i]-1]; 52 if(k) k--; 53 while(c[i+k]==c[j+k] && i+k<=cl && j+k<=cl) k++; 54 h[rk[i]]=k; 55 } 56 h[0]=0; 57 } 58 59 int idx(int x) 60 { 61 for(int i=1;i<=n;i++) 62 if((st[i]<=x && x<=ed[i]) || (fst[i]<=x && x<=fed[i])) return i; 63 } 64 65 bool check(int k) 66 { 67 memset(vis,0,sizeof(vis)); 68 for(int i=1;i<=cl;i++) 69 { 70 if(h[i]
1) c[++cl]=++num;100 st[i]=cl+1;for(int j=1;j<=sl;j++) c[++cl]=s[j];ed[i]=cl;101 c[++cl]=++num;102 fst[i]=cl+1;for(int j=sl;j>=1;j--) c[++cl]=s[j];fed[i]=cl;103 }104 if(n==1) {printf("%d\n",sl);continue;}105 get_sa(300);106 get_h();107 // for(int i=1;i<=cl;i++) printf("%c",c[i]);printf("\n");108 // for(int i=1;i<=cl;i++) printf("%d ",c[i]);printf("\n");109 // for(int i=1;i<=cl;i++) printf("%d ",sa[i]);printf("\n");110 // for(int i=1;i<=cl;i++) printf("%d ",rk[i]);printf("\n");111 // for(int i=1;i<=cl;i++) printf("%d ",h[i]);printf("\n");112 int l=0,r=cl,mid;113 while(l

 

这一题我曾经用kmp暴力水过。。贴一下代码

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 9 const int N=110,Inf=(int)1e9;10 char s[N][N],c1[N],c2[N];11 int n,id,cl,l[N],nt[N],nxt[N];12 13 void kmp_nt()14 {15 nt[1]=0;16 for(int i=2,p=0;i<=cl;i++)17 {18 while(c1[p+1]!=c1[i] && p) p=nt[p];19 if(c1[p+1]==c1[i]) p++;20 nt[i]=p;21 }22 23 nxt[1]=0;24 for(int i=2,p=0;i<=cl;i++)25 {26 while(c2[p+1]!=c2[i] && p) p=nxt[p];27 if(c2[p+1]==c2[i]) p++;28 nxt[i]=p;29 }30 }31 32 bool kmp_td(int x)33 {34 for(int i=1,p=0;i<=l[x];i++)35 {36 while(c1[p+1]!=s[x][i] && p) p=nt[p];37 if(c1[p+1]==s[x][i]) p++;38 if(p==cl) return 1;39 }40 for(int i=1,p=0;i<=l[x];i++)41 {42 while(c2[p+1]!=s[x][i] && p) p=nxt[p];43 if(c2[p+1]==s[x][i]) p++;44 // td[i]=p;45 if(p==cl) return 1;46 }47 return 0;48 }49 50 bool check(int len)51 {52 for(int i=1;i+len-1<=l[id];i++)53 {54 cl=0;55 for(int j=i;j<=i+len-1;j++) 56 c1[++cl]=s[id][j],c2[len-cl+1]=s[id][j];57 kmp_nt();58 bool bk=1;59 for(int j=1;j<=n;j++)60 if(!kmp_td(j)) {bk=0;break;}61 if(bk) return 1;62 }63 }64 65 int main()66 {67 freopen("a.in","r",stdin);68 freopen("vio.out","w",stdout);69 int T;70 scanf("%d",&T);71 while(T--)72 {73 scanf("%d",&n);74 int ll=0,rr=Inf,mid;75 for(int i=1;i<=n;i++)76 {77 scanf("%s",s[i]+1);78 l[i]=strlen(s[i]+1);79 if(l[i]

 

转载于:https://www.cnblogs.com/KonjakJuruo/p/5909018.html

你可能感兴趣的文章
docker入门
查看>>
Android系统--输入系统(十一)Reader线程_简单处理
查看>>
监督学习模型分类 生成模型vs判别模型 概率模型vs非概率模型 参数模型vs非参数模型...
查看>>
Mobiscroll脚本破解,去除Trial和注册时间限制【转】
查看>>
实验五 Java网络编程及安全
查看>>
32位与64位 兼容编程
查看>>
iframe父子页面通信
查看>>
ambari 大数据安装利器
查看>>
java 上传图片压缩图片
查看>>
magento 自定义订单前缀或订单起始编号
查看>>
ACM_拼接数字
查看>>
计算机基础作业1
查看>>
Ubuntu 深度炼丹环境配置
查看>>
C#中集合ArrayList与Hashtable的使用
查看>>
从一个标准 url 里取出文件的扩展名
查看>>
map基本用法
查看>>
poj-1163 动态规划
查看>>
Golang之interface(多态,类型断言)
查看>>
Redis快速入门
查看>>
BootStrap---2.表格和按钮
查看>>