hdu4763 KMP
稀里糊涂1A开心。我做了2次kmp,先第一次利用next[],由于next[]前面一小段一直是一样的,所以可以根据这个来找。然后就找到了开头和结尾,还缺中间的部分。
中间的部分就是通过开头部分去模式匹配,如果有就直接输出,break就可以。(因为开始长度最长)
#include<stdio.h> #include<string.h> #define maxn 1000010 int next[maxn],nexts1[maxn]; char s[maxn],s1[maxn],s2[maxn],flag; void getnext() { int j,k,len=strlen(s); j=0; k=-1; next[0]=-1; while(j<len) { if(k==-1||s[j]==s[k]) { j++; k++; next[j]=k; } else k=next[k]; } } int KMP() { int i,j,k,len=strlen(s1); k=-1; j=0; nexts1[0]=-1; while(j<len) { if(k==-1||s1[j]==s1[k]) { j++; k++; nexts1[j]=k; } else k=nexts1[k]; } j=0; i=0; int fl=strlen(s2); while(i<fl) { if(j==-1||s1[j]==s2[i]) { i++; j++; } else j=nexts1[j]; if(j==strlen(s1)) { return 1; } } return 0; } void kmp() { int i,j,len=strlen(s),ans; getnext(); i=len-1; while(next[i]!=-1) { int k=0,p=0; flag=1; if(s[next[i]]!=s[i])//这里我是这样想的 如果当前的和他next[]的值不一样,那就要继续往下找 i=next[i]; for(j=0;j<=next[i];j++) s1[k++]=s[j]; s1[k]='\0'; if(s1[0]=='\0') { flag=0; break; } for(j=next[i]+1;j<len-1-next[i];j++) s2[p++]=s[j]; s2[p]='\0'; if(!KMP()) { flag=0; } else { ans=strlen(s1); break; } i=next[i]; //printf("%s %s\n",s1,s2); } if(flag==0) { printf("0\n"); } else printf("%d\n",ans); } int main() { int i,j,t; scanf("%d",&t); while(t--) { scanf("%s",s); if(strlen(s)<3) { printf("0\n"); continue; } kmp(); } }