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

题解:

对于每个串,把反转串也连进去。
二分长度,分组,判断每个组。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; const int N=*;
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];
char s[N];
bool vis[N]; void get_sa(int m)
{
for(int i=;i<=cl;i++) rk[i]=c[i];
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[rk[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i; int ln=,p=;
while(p<cl)
{
int k=;
for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln; for(int i=;i<=cl;i++) wr[i]=rk[y[i]];
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[wr[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=;rk[sa[]]=;
for(int i=;i<=cl;i++)
{
if(wr[sa[i]]!=wr[sa[i-]] || wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rk[sa[i]]=p;
}
ln*=,m=p;
}
sa[]=,rk[]=;
} void get_h()
{
int k=,j;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
j=sa[rk[i]-];
if(k) k--;
while(c[i+k]==c[j+k] && i+k<=cl && j+k<=cl) k++;
h[rk[i]]=k;
}
h[]=;
} int idx(int x)
{
for(int i=;i<=n;i++)
if((st[i]<=x && x<=ed[i]) || (fst[i]<=x && x<=fed[i])) return i;
} bool check(int k)
{
memset(vis,,sizeof(vis));
for(int i=;i<=cl;i++)
{
if(h[i]<k)
{
int cnt=;
for(int j=;j<=n;j++) if(vis[j]) cnt++;
if(cnt==n) return ;
memset(vis,,sizeof(vis));
}
vis[idx(sa[i])]++;
}
int cnt=;
for(int j=;j<=n;j++) if(vis[j]) cnt++;
if(cnt==n) return ;
return ;
} int main()
{
freopen("a.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int num=;
cl=;
for(int i=;i<=n;i++)
{
scanf("%s",s+);
sl=strlen(s+);
if(i>) c[++cl]=++num;
st[i]=cl+;for(int j=;j<=sl;j++) c[++cl]=s[j];ed[i]=cl;
c[++cl]=++num;
fst[i]=cl+;for(int j=sl;j>=;j--) c[++cl]=s[j];fed[i]=cl;
}
if(n==) {printf("%d\n",sl);continue;}
get_sa();
get_h();
// for(int i=1;i<=cl;i++) printf("%c",c[i]);printf("\n");
// for(int i=1;i<=cl;i++) printf("%d ",c[i]);printf("\n");
// for(int i=1;i<=cl;i++) printf("%d ",sa[i]);printf("\n");
// for(int i=1;i<=cl;i++) printf("%d ",rk[i]);printf("\n");
// for(int i=1;i<=cl;i++) printf("%d ",h[i]);printf("\n");
int l=,r=cl,mid;
while(l<r)
{
mid=(l+r+)/;
if(check(mid)) l=mid;
else r=mid-;
}
printf("%d\n",l);
}
return ;
}

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

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; const int N=,Inf=(int)1e9;
char s[N][N],c1[N],c2[N];
int n,id,cl,l[N],nt[N],nxt[N]; void kmp_nt()
{
nt[]=;
for(int i=,p=;i<=cl;i++)
{
while(c1[p+]!=c1[i] && p) p=nt[p];
if(c1[p+]==c1[i]) p++;
nt[i]=p;
} nxt[]=;
for(int i=,p=;i<=cl;i++)
{
while(c2[p+]!=c2[i] && p) p=nxt[p];
if(c2[p+]==c2[i]) p++;
nxt[i]=p;
}
} bool kmp_td(int x)
{
for(int i=,p=;i<=l[x];i++)
{
while(c1[p+]!=s[x][i] && p) p=nt[p];
if(c1[p+]==s[x][i]) p++;
if(p==cl) return ;
}
for(int i=,p=;i<=l[x];i++)
{
while(c2[p+]!=s[x][i] && p) p=nxt[p];
if(c2[p+]==s[x][i]) p++;
// td[i]=p;
if(p==cl) return ;
}
return ;
} bool check(int len)
{
for(int i=;i+len-<=l[id];i++)
{
cl=;
for(int j=i;j<=i+len-;j++)
c1[++cl]=s[id][j],c2[len-cl+]=s[id][j];
kmp_nt();
bool bk=;
for(int j=;j<=n;j++)
if(!kmp_td(j)) {bk=;break;}
if(bk) return ;
}
} int main()
{
freopen("a.in","r",stdin);
freopen("vio.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int ll=,rr=Inf,mid;
for(int i=;i<=n;i++)
{
scanf("%s",s[i]+);
l[i]=strlen(s[i]+);
if(l[i]<rr) rr=l[i],id=i;
}
while(ll<rr)
{
mid=(ll+rr+)/;
if(check(mid)) ll=mid;
else rr=mid-;
}
printf("%d\n",ll);
}
return ;
}

【poj1226-出现或反转后出现在每个串的最长公共子串】后缀数组的更多相关文章

  1. Java算法——求出两个字符串的最长公共字符串

    问题:有两个字符串str1和str2,求出两个字符串中最长公共字符串. 例如:“acbbsdef”和"abbsced"的最长公共字符串是“bbs” 算法思路: 1.把两个字符串分别 ...

  2. POJ1226 Substrings ——后缀数组 or 暴力+strstr()函数 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-1226 Substrings Time Limit: 1000MS   Memory Limit: 10000K Total ...

  3. POJ 3294 出现在至少K个字符串中的子串

    在掌握POJ 2774(两个串求最长公共子串)以及对Height数组分组后,本题还是容易想出思路的. 首先用字符集外的不同字符连接所有串,这是为了防止两个后缀在比较时超过某个字符串的分界.二分子串的长 ...

  4. POJ1226:Substrings(后缀数组)

    Description You are given a number of case-sensitive strings of alphabetic characters, find the larg ...

  5. [POJ1226]Substrings(后缀数组)

    传送门 给定 n 个字符串,求出现或反转后出现在每个字符串中的最长子串. 算法分析: 这题不同的地方在于要判断是否在反转后的字符串中出现.其实这并没有加大题目的难度. 只需要先将每个字符串都反过来写一 ...

  6. array_flip() 函数返回一个反转后的数组

    定义和用法 array_flip() 函数返回一个反转后的数组,如果同一值出现了多次,则最后一个键名将作为它的值,所有其他的键名都将丢失. 如果原数组中的值的数据类型不是字符串或整数,函数将报错 ar ...

  7. 调用百度地图API的应用混淆后出问题

    1 混淆后出问题,程序异常退出 在proguard-project.txt中添加 -libraryjars libs/BaiduLBS_Android.jar -keep class com.baid ...

  8. 动态规划:给出两个字符串s1和s2,返回其中最大的公共子串

    求公共子字符串问题(连续的) 这个题目是当时远景能源公司现场笔试的一道题目,当时根本就不知道动态规划是什么鬼,直接上来就暴力求解,面试官很谄媚的问我,你这能求出来吗?当时很年轻的说,能啊!现在想,当时 ...

  9. C#中的字符串处理——找出最长数字子串

    百度测试部2015年10月份的面试题之——字符串处理,找出最长的子串. 代码如下: private static string SelectNumberFromString(string input) ...

随机推荐

  1. 6.1 python+appium元素定位方式(登录app)

    1.0.0     :常见的十种元素定位方式 .driver.find_element_by_id() #id定位 .driver.find_element_by_name() #name定位(已经凉 ...

  2. 功能规格说明书Version2

    此功能规格说明书是Week8 功能规格说明书的第二个版本, 版本1地址:http://www.cnblogs.com/Z-XML/p/3407687.html 此功能规格说明书是面向用户的,所以作者将 ...

  3. nopcommerce商城系统--安装nopCommerce

    原址:http://www.nopcommerce.com/docs/79/installing-nopcommerce.aspx .NET Framework 4.5.1下载:http://www. ...

  4. Source Tree基础教程2

    1.分支 项目——分支——推送 新分支要重新拉取项目后才可以看见 项目——拉取 2合并分支代码 将其他分支代码合并到当前分支——提交

  5. regex & form validation & phone

    regex & form validation https://regexper.com/ https://gitlab.com/javallone/regexper-static https ...

  6. java解析XML的方法

    1.DOM 实现方法 xml文件 <?xml version="1.0" encoding="utf-8"?> <Accounts> & ...

  7. Intellij IDEA 系统路径配置

    在使用IDEA启动Tomcat的时候,会读取系统路径,默认路径可能不是我们想要的,可以修改 C:\MyPrograms\IntelliJ IDEA 14.0.1\bin\idea.properties ...

  8. viterbi维特比算法和隐马尔可夫模型(HMM)

    隐马尔可夫模型(HMM) 原文地址:http://www.cnblogs.com/jacklu/p/7753471.html 本文结合了王晓刚老师的ENGG 5202 Pattern Recognit ...

  9. jQuery插件jquery.fullPage.js

    简介如今我们经常能看到全屏网站,尤其是国外网站.这些网站用几幅很大的图片或者色块做背景,再添加一些简单的内容,显得格外的高端大气上档次,比如 iPone 5C 的介绍页面.QQ浏览器的官方网站.百度史 ...

  10. hdu 3496 Watch The Movie (二维背包)

    Watch The Movie Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...