hdu 4300(kmp)
题意:说实话这个题的题意还真的挺难懂的,我开始看了好久都没看懂,后来百度了下题意才弄懂了,这题的意思就是首先有一个字母的转换表,就是输入的第一行的字符串,就是'a'转成第一个字母,'b'转成转换表的第二个字母·······然后下面一个字符串是密文+明文的形式的字符串。就是说前后两段是重复的,只不过通过转换表转换了下。而且后面一段可能不完整,让我们补完整。
思路:这道题我很久之前就已经a掉了,当时是用普通的kmp做的,稍微变通下就行了。只不过现在正在学习扩展kmp,所以就用扩展kmp做了下,个人觉得普通的kmp还好一点,代码短也容易理解。
我现在讲两种方法:
第一种、普通的kmp首先题目中输入的字符串:密文+明文,假设该字符串为s1,第一步:把s1全部翻译一遍变成:明文+密文,假设该字符串为s2;第二步:我们以s1的后半段为主串,以s2为模式串进行kmp即可。
代码实现:
#include<iostream> #include<cstring> using namespace std; char a[100001],c[100001]; int next[100001]; int main() { int T,i,j,len,nima[27],mid; char b[27]; while(scanf("%d",&T)!=EOF) { getchar(); while(T--) { scanf("%s%s",b+1,a+1); for(i=1;i<=26;i++) nima[b[i]-'a']=i-1; len=strlen(a+1); for(i=1;i<=len;i++) c[i]='a'+nima[a[i]-'a']; i=1;j=0;next[1]=0; while(i<len) { if(j==0||c[i]==c[j]) { i++;j++; next[i]=j; } else j=next[j]; } if(len%2==0) i=len/2+1; else i=len/2+2; j=1;mid=i; while(i<=len) { if(j==0||a[i]==c[j]) { i++;j++; } else j=next[j]; } for(i=1;i<=len;i++) printf("%c",a[i]); for(i=j;i<j+len-2*j+2;i++) printf("%c",c[i]); printf("\n"); } } return 0; }
第二种、扩展kmp,首先题目中输入的字符串:密文+明文,假设该字符串为s1,第一步:把s1 的后半段翻译译一遍变成:假设该字符串为s2;第二步:以s1为主串,s2为模式串进行一次扩展kmp,得到extend数组;第三步:对extend数组进行一次扫描,如果主串某一位置的后缀与模式串的前缀全部匹配就立即停止,这一位置就是满足的最优解了。
代码实现:
#include<stdio.h> #include<string.h> char str1[26],T[100005]; char s1[26],S[100005]; int next[100005],extend[100005]; void get_next() { int len=strlen(T),j,a,k,p,L; next[0]=len; a=0; while(a<len-1&&T[a]==T[a+1]) a++; next[1]=a; a=1; for(k=2;k<len;k++) { p=a+next[a]-1; L=next[k-a]; if(k+L-1>=p) { j=p-k+1>0?p-k+1:0; while(j+k<len&&T[j+k]==T[j]) j++; next[k]=j; a=k; } else next[k]=L; } } void get_extend()//S为主串,T为模式串 { int len1,len2,len,j,k,a,p,L; get_next(); len1=strlen(S); len2=strlen(T); len=len1>len2?len2:len1; a=0; while(a<len&&S[a]==T[a]) a++; extend[0]=a; a=0; for(k=1;k<len1;k++) { p=a+extend[a]-1; L=next[k-a]; if(k+L-1>=p) { j=p-k+1>0?p-k+1:0; while(j+k<len1&&j<len2&&S[j+k]==T[j]) j++; extend[k]=j; a=k; } else extend[k]=L; } } int main() { int t,i,len,mid,max,len1; while(scanf("%d",&t)!=EOF) { getchar(); while(t--) { max=-1; scanf("%s",str1); scanf("%s",T); for(i=0;i<26;i++) s1[str1[i]-'a']=i+'a'; len=strlen(T); if(len%2==0) mid=len/2; else mid=len/2+1; for(i=mid;i<len;i++) S[i-mid]=str1[T[i]-'a']; S[i-mid]='\0'; get_extend(); len=strlen(S); len1=strlen(T); for(i=0;i<len;i++) if(i+mid+extend[i]==len1) { max=extend[i]; break; } printf("%s",T); if(max==-1) max=0; len=strlen(T); for(i=max;i<len-max;i++) printf("%c",s1[T[i]-'a']); printf("\n"); } } return 0; }
posted on 2013-07-13 17:31 后端bug开发工程师 阅读(1983) 评论(0) 编辑 收藏 举报