亲和串的定义是这样的:给定两个字符串s1和s2,如果能通过s1循环移位,使s2包含在s1中,那么我们就说s2 是s1的亲和串。
AABCD CDAA ASD ASDF
yes no//这是一道非常简单的kmp算法的题目,关键就是在题目里的移位循环,其实这句话告诉了我们两个信息,一个是s1串必须比s2串要长,否则无法包涵,其次是移位循环的概念,它并不是指字符串的首尾相连,而是将母串整个的复制一遍,复制到原来的母串的后面。下面是代码。代码:#include<stdio.h> #include<string.h> #include<iostream> #include<stdio.h> #include<stdlib.h>
using namespace std;
void getnextval(char *p,int next[]) { int i=-1; int j=0; next[0]=-1; while(p[j]!='\0') { if(i==-1||p[i]==p[j]) { i++; j++; if(p[i]!=p[j]) { next[j]=i; } else next[j]=next[i]; } else i=next[i]; } }
int kmp(char *T,char *p) { if(!T||!p||T[0]=='\0'||p[0]=='\0') return -1; int len=0; char *c=p; while(*c++!='\0') ++len; int *next=new int[len+1]; getnextval(p,next); int index=0,i=0,j=0; while(T[i]!='\0'&&p[j]!='\0') { if(T[i]==p[j]) { i++; j++; } else { index+=j-next[j]; if(next[j]!=-1) j=next[j]; else { j=0; ++i; } } } delete []next; if(p[j]=='\0') cout<<"yes"<<endl; else cout<<"no"<<endl; }
int main() { char s1[100005]; char s2[100005]; char s3[100005]; int l1,l2,l3; while(scanf("%s%s",s1,s2)!=EOF) { l1=strlen(s1); l2=strlen(s2); if(l1<l2) cout<<"no"<<endl; else { strcpy(s3,s1); l3=strlen(s3); for(int i=0;i<l3;i++) s3[l3+i]=s1[i];//关键就在这一步将s3变成是s1后面在复制一个s1的串,这样就实现了循环移位,用kmp得出了结果。 kmp(s3,s2); } } return 0; }