[10.5模拟] dis

题意:给你一个主串,两个分串,要求两个分串的距离最大,两个分串的距离定义为第一个分串的最右边的字符和第二个分串的最左边的字符之间的字符数

题解:

直接kmp匹配两个分串即可

注:kmp匹配时,当分串与主串匹配成功时,j不要重新从0开始

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define N 100010
using namespace std;

int tot,nxt1[N],nxt2[N],L=-1,R=-1;
char S[N<<2],s1[N],s2[N],s[N];

int gi() {
  int x=0,o=1; char ch=getchar();
  while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
  return o*x;
}

void get_nxt1() {
  int n=strlen(s1+1),i,j;
  for(i=2; i<=n; i++) {
    j=nxt1[i-1];
    while(j && s1[j+1]!=s1[i]) j=nxt1[j];
    nxt1[i]=s1[j+1]==s1[i]?j+1:0;
  }
}

void get_nxt2() {
  int n=strlen(s2+1),i,j;
  for(i=2; i<=n; i++) {
    j=nxt2[i-1];
    while(j && s2[j+1]!=s2[i]) j=nxt2[j];
    nxt2[i]=s2[j+1]==s2[i]?j+1:0;
  }
}

void kmp1() {
  int i,j=0,n=strlen(s+1),m=strlen(s1+1);
  for(i=1; i<=n; i++) {
    while(s1[j+1]!=s[i] && j) j=nxt1[j];
    if(s1[j+1]==s[i]) j++;
    if(j==m) {L=i;break;}
  }
}

void kmp2() {
  int i,j=0,n=strlen(s+1),m=strlen(s2+1);
  for(i=1; i<=n; i++) {
    while(s2[j+1]!=s[i] && j) j=nxt2[j];
    if(s2[j+1]==s[i]) j++;
    if(j==m) R=i;
  }
}

int main() {
  int i,n,k=0;
  scanf("%s", S+1);
  n=strlen(S+1);
  for(i=1; i<=n; i++) {
    if(S[i]==',') break;
    s[i]=S[i];
  }
  for(i++; i<=n; i++) {
    if(S[i]==',') break;
    s1[++k]=S[i];
  }
  k=0;
  for(i++; i<=n; i++) {
    s2[++k]=S[i];
  }
  get_nxt1(),get_nxt2();
  kmp1(),kmp2();
  n=strlen(s2+1);
  if(L==-1 || R==-1) {puts("-1");return 0;}
  if(L<R-n+1) {
    printf("%d", R-n-L);
  }
  else puts("-1");
  return 0;
}
posted @ 2017-10-06 16:16  HLX_Y  阅读(160)  评论(0)    收藏  举报