标签:read number hat 文本 相等 begin bcd earth output
题目链接:http://poj.org/problem?id=3080
Input
Output
Sample Input
3 2 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 3 GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA 3 CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Sample Output
no significant commonalities AGATAC CATCATCAT
题目思路:首先一点:我们都是利用第一个字符串作为比较(截取其中一部分作为模式串)
两个概念:
文本串:就是待查找(询)的字符串(比如abcde)
模式串:就是要在文本串中查找的字符串(比如bcd,和上面对应的模式串)
首先思路一是大家都想得到的暴力枚举法(但是因为本人是个蒟蒻,有些函数还不会用,不知道怎么实现555~),那就是从第一个字符串中列举所有按长度值递增的字符串(长度值一样按照串的起始位置从前往后取,注意选取的字符串最后一位不要越界)与除此之外的后面所有字符串比较,如果选取的字符串(长度大于等于3)在后面的待比较的字符串中均有出现。则输出该字符串;否则输出
no significant commonalities
题目思路二是列举截取第一个字符串的起始地址而不需要列举它的长度,而只需要用 截取的字符串 和每个字符串(第2个到第n个)kmp匹配到指针在模式串中所能达到的最大距离当中取最小的,就是我们要的答案了。
然后代码如下:
//POJ3080 //暴力枚举法 #include<iostream> #include<string> using namespace std; int t,n; string s[11]; int main() { cin>>t; while(t--) { cin>>n; string snk="no significant commonalities"; for(int i=1;i<=n;i++)cin>>s[i]; for(int i=3;i<=60;i++)//列举长度3-60 { for(int j=0;j<=60-i;j++)//列举长度为i的字符串从哪里开始 { string mo=s[1].substr(j,i);//s[1]中从j开始长度为i的字符串付给mo bool flag=true; for(int k=2;k<=n;k++)//从s[2]开始对比 { if(s[k].find(mo)==string::npos)//没有查找到 { flag=false; break; } } if(!flag)continue;//没有就重来 else//如果找到了 { if(snk=="no significant commonalities")snk=mo; else if(snk.size()<mo.size())snk=mo; else if(snk.size()==mo.size())snk=min(snk,mo); } } } cout<<snk<<endl; } return 0; }
//POJ3080 //暴力枚举法 /* #include<iostream> #include<string> using namespace std; int t,n; string s[11]; int main() { cin>>t; while(t--) { cin>>n; string snk="no significant commonalities"; for(int i=1;i<=n;i++)cin>>s[i]; for(int i=3;i<=60;i++)//列举长度3-60 { for(int j=0;j<=60-i;j++)//列举长度为i的字符串从哪里开始 { string mo=s[1].substr(j,i);//s[1]中从j开始长度为i的字符串付给mo bool flag=true; for(int k=2;k<=n;k++)//从s[2]开始对比 { if(s[k].find(mo)==string::npos)//没有查找到 { flag=false; break; } } if(!flag)continue;//没有就重来 else//如果找到了 { if(snk=="no significant commonalities")snk=mo; else if(snk.size()<mo.size())snk=mo; else if(snk.size()==mo.size())snk=min(snk,mo); } } } cout<<snk<<endl; } return 0; } */ //kmp算法 #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<iomanip> #include<list> #include<map> #include<queue> #include<sstream> #include<stack> #include<string> #include<set> #include<vector> using namespace std; #define PI acos(-1.0) #define pppp cout<<endl; #define EPS 1e-8 #define LL long long #define ULL unsigned long long //1844674407370955161 #define INT_INF 0x3f3f3f3f //1061109567 #define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399 // ios::sync_with_stdio(false); // 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。 const int dr[]= {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[]= {-1, 1, 0, 0, -1, 1, -1, 1}; inline int read()//输入外挂 { int ret=0, flag=0; char ch; if((ch=getchar())==‘-‘) flag=1; else if(ch>=‘0‘&&ch<=‘9‘) ret = ch - ‘0‘; while((ch=getchar())>=‘0‘&&ch<=‘9‘) ret=ret*10+(ch-‘0‘); return flag ? -ret : ret; } char s[10][1010];//待匹配串 char s2[1010]; char str[1010];//输出 int Next[1010];//优化后的失配指针,记住这里f要比P多一位,因为P到m-1即可,但是f还要计算出m的失配指针 int Next2[1010];//Next2用来保存KM指针,是为优化f的失配指针,f保存的是优化之后的失配指针 int ma; int n; void getFail(int len)//对于s2字符串生成(优化后的)Next和Next2数组 { Next[0]=Next[1] = 0; Next2[0]=Next2[1]=0; for(int i=1; i<len; i++)//len为s2长度 { int j=Next2[i]; while(j&&s2[i]!=s2[j] )//一直循环到他们对应的字符相等 如果一直不相等(即找不到前后缀一样的)那此时j就为0了 j=Next2[j]; Next2[i+1]=Next[i+1]=(s2[i]==s2[j])?j+1:0;//0表示如果上面循环还是没找到相同前缀后缀那么i+1的元素不匹配下一步归零 if(Next[i+1]==j+1 && s2[i+1]==s2[j+1]) Next[i+1]=Next[j+1]; } } void Find(int x,int len) //找到所有匹配点 { getFail(len); ma=100; for(int k=1;k<n;++k)//n是待匹配的字符串下标 { int j=0; int m=0; for(int i=0; i<x&&j<len; i++) { while(j && s[k][i]!=s2[j]) j=Next[j]; if(s[k][i]==s2[j]) j++; if(j>m)//寻找长的 m=j; } if(m<ma)ma=m;//只有小的能包含长的 } } int main() { //freopen("D:\\chnegxubianji\\inORout\\in.txt", "r", stdin); //freopen("D:\\chnegxubianji\\inORout\\out.txt", "w", stdout); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0; i<n; i++) scanf("%s",s[i]); int anslen=0;//最终长度 for(int i=0; i<=57; i++) { strcpy(s2,s[0]+i);//从s[0][0+i]开始到结尾复制到s2当中 int len=60-i;//所以长度为60-i Find(60,len); if(ma>anslen)//找到长度大于之前的 { anslen=ma; strncpy(str,s[0]+i,ma); str[anslen]=‘\0‘; } else if(ma==anslen)//相同长度寻找字典序小的 { strncpy(s2,s[0]+i,anslen); s2[anslen]=‘\0‘; if(strcmp(s2,str)<0) { strcpy(str,s2); str[anslen]=‘\0‘; } } } if(anslen>=3) printf("%s\n",str); else puts("no significant commonalities"); } return 0; }
标签:read number hat 文本 相等 begin bcd earth output
原文地址:https://www.cnblogs.com/Mingusu/p/11799788.html