Poj 3080 Blue Jeans
题意:求n个长度为60的字符串的最长连续公共子串,2<=n<=10
1、 最长公共串长度小于3不输出
2、 若出现等长的最长的子串,则输出字典序最小的串
思路:和Poj 3294 Life Forms差不多,只不过变成了只输出第一个。
据说暴力也可以过。。。暴力法参考代码及测试数据:http://blog.csdn.net/lyy289065406/article/details/6647262
尤其注意最后一组测试数据
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int N = int(1e4)+100;
int cmp(int *r,int a,int b,int l){
return (r[a]==r[b]) && (r[a+l]==r[b+l]);
}
int wa[N],wb[N],ws[N],wv[N];
int rank[N],height[N];
void DA(int *r,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=r[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[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(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
//printf("p = %d\n", p );
}
}
void calheight(int *r,int *sa,int n){
// memset(height,0,sizeof(height));
// memset(rank,0,sizeof(rank));
int i,j,k=0;
for(i=1;i<=n;i++) rank[sa[i]]=i;
for(i=0;i<n; height[rank[i++]] = k )
for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
}
int data[N],loc[N],sa[N],temp[N];
int n,q,ans[N],id;
char str[105];
bool vis[105];
bool Judge (int x)
{
int i,j;
bool flag=false;
for (i=1;i<=n;i++)
{
int cnt=0;
int L=i;
while (L<=n && height[L]<x)
L++;
if (L>n) break;
int R=L;
while (R<=n && height[R]>=x)
R++;
memset(vis,false,sizeof(vis));
for (j=L-1;j<=R-1;j++)
if (loc[sa[j]]!=-1)
vis[loc[sa[j]]]=true;
for (j=1;j<=q;j++)
if (vis[j])
cnt++;
if (cnt==q)
if (flag)
ans[++id]=sa[L-1];
else
{
ans[id=1]=sa[L-1];
flag=true;
}
i=R;
}
return flag;
}
void Input ()
{
int i,de=170;//分隔符
n=0;
scanf("%d",&q);
memset(data,0,sizeof(data));
for (int id=1;id<=q;id++)
{
scanf("%s",str);
int len=strlen(str);
for (i=0;i<len;i++)
{
loc[n]=id;
data[n++]=(int)str[i];
}
loc[n]=-1;
data[n++]=de++; //注意分隔符需变化
}
data[n]=0;
}
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
for (int Cas=1;Cas<=T;Cas++)
{
Input ();
DA(data,sa,n+1,300);
calheight(data,sa,n);
int low=0,high=n,mid,res=0;
while (low<high)
{
mid = (low+high)>>1;
if (Judge(mid))
res=mid,low=mid+1;
else
high=mid;
}
if (res<3)
printf("no significant commonalities\n");
else
{
int k=ans[1]; //字典序最小一定第一个
for (int j=0;j<res;j++) //res子串长度
printf("%c",(char)data[k+j]);
printf("\n");
}
}
return 0;
}
Hdu 2328 Corporate Identity
和上面那题基本一样。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int N = int(8e5)+100;
int cmp(int *r,int a,int b,int l){
return (r[a]==r[b]) && (r[a+l]==r[b+l]);
}
int wa[N],wb[N],ws[N],wv[N];
int rank[N],height[N];
void DA(int *r,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=r[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[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(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
//printf("p = %d\n", p );
}
}
void calheight(int *r,int *sa,int n){
// memset(height,0,sizeof(height));
// memset(rank,0,sizeof(rank));
int i,j,k=0;
for(i=1;i<=n;i++) rank[sa[i]]=i;
for(i=0;i<n; height[rank[i++]] = k )
for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
}
int data[N],loc[N],sa[N];
int n,q,id,start;
char str[205];
bool vis[4005];
bool Judge (int x)
{
int i,j;
bool flag=false;
for (i=1;i<=n;i++)
{
int cnt=0;
int L=i;
while (L<=n && height[L]<x)
L++;
if (L>n) break;
int R=L;
while (R<=n && height[R]>=x)
R++;
memset(vis,false,sizeof(vis));
for (j=L-1;j<=R-1;j++)
if (loc[sa[j]]!=-1)
vis[loc[sa[j]]]=true;
for (j=1;j<=q;j++)
if (vis[j])
cnt++;
if (cnt==q)
{
start=sa[L-1];
return true;
}
i=R;
}
return false;
}
void Input ()
{
int i,de=170;//分隔符
n=0;
memset(data,0,sizeof(data));
for (int id=1;id<=q;id++)
{
scanf("%s",str);
int len=strlen(str);
for (i=0;i<len;i++)
{
loc[n]=id;
data[n++]=(int)str[i];
}
loc[n]=-1;
data[n++]=de++; //注意分隔符需变化
}
data[n]=0;
DA(data,sa,n+1,++de); //分隔符可能很大
calheight(data,sa,n);
}
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
while (~scanf("%d",&q),q)
{
Input ();
int low=0,high=n,mid,res=0;
while (low<high)
{
mid = (low+high)>>1;
if (Judge(mid))
res=mid,low=mid+1;
else
high=mid;
}
if (res==0)
printf("IDENTITY LOST\n");
else
{
int k=start;
for (int j=0;j<res;j++) //res子串长度
printf("%c",(char)data[k+j]);
printf("\n");
}
}
return 0;
}