给定N个物种的基因序列,若俩个序列s1和s2的最长公共子串长度len满足 |s1|*p<len && |s2|*p<len (p是题目给定的百分比),则俩个物种属于同一类,问这N个物种可以分为几类
分析:额,LCS+并查集
View Code
#include<iostream> #include<algorithm> #include<string> #include<vector> using namespace std; const int N = 100+10; int n,f[N]; double p; char str[N][N]; void init() { for(int i=0;i<n;i++) f[i]=i; } int find(int x) { if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } int LCS(const char *str1,const char *str2) { int xlen=strlen(str1); //横向长度 int tmp[N]={0}; //保存矩阵的上一行 int arr[N]={0}; //当前行 int ylen=strlen(str2); //纵向长度 int maxele=0; //矩阵元素中的最大值 int pos=0; //矩阵元素最大值出现在第几列 for(int i=0;i<xlen;i++) { for(int j=0;j<ylen;j++) { arr[j]=0; if(str1[i]==str2[j]) { if(j==0) arr[j]=1; else arr[j]=tmp[j-1]+1; if(arr[j]>maxele) { maxele=arr[j]; pos=j; } } } for(int j=0;j<ylen;j++) tmp[j]=arr[j]; } return maxele; } int main() { int cas=0; while(scanf("%d %lf",&n,&p)==2) { init(); for(int i=0;i<n;i++) scanf("%s",str[i]); for(int i=0;i<n;i++) { int a=find(i); int len1=strlen(str[i]); for(int j=i+1;j<n;j++) { int b=find(j); if(a==b)//若已经属于同一类了,就不需要求了 continue; int len=LCS(str[i],str[j]); int len2=strlen(str[j]); if(len1*p*0.01<len && len2*p*0.01<len) f[b]=a; } } int ans=0; for(int i=0;i<n;i++) { if(i==find(i)) ans++; } printf("Case %d:\n%d\n",++cas,ans); } return 0; }