题解:
KMP即可。先用第一个串从头开始匹配,再反转标准串和第二个串,再匹配一次,然后用两个位置处理出答案,细节就是该怎么减和-1的判断。注意读入用getchar,我用gets要1000ms+,用getchar直接0ms。
简谈一下KMP,先处理出短串的Next数组,即最长相同前后缀长度,方便我们匹配失败后直接跳到下一个相同开头的地方。
然后再用类似的方法匹配标准串,利用Next数组可以在匹配失败的时候直接跳到下一个符合条件的地方,大幅缩短匹配时间。
时间复杂度O(0)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define MAXA 100005
using namespace std;
char Std[MAXA],S1[MAXA],S2[MAXA],Temp;
int StdLen,Len1,Len2,pos,Next[MAXA],k,Left = -1,Right = -1;
bool Flag;
int main() {
// freopen("dis.in","r",stdin);
// freopen("dis.out","w",stdout);
while((Temp = getchar()) && Temp != ',')
Std[StdLen++] = Temp;
while((Temp = getchar()) && Temp != ',')
S1[Len1++] = Temp;
while((Temp = getchar()) && Temp != '\n')
S2[Len2++] = Temp;
if(Len1 + Len2 > StdLen) {
printf("-1");
return 0;
}
Next[0] = k = -1;
for(int i=1;i<Len1;i++) {
while(k > -1 && S1[k + 1] != S1[i])
k = Next[k];
if(S1[k + 1] == S1[i])
k++;
Next[i] = k;
}
k = -1;
for(int i=0;i<StdLen;i++) {
while(k > -1 && Std[i] != S1[k + 1])
k = Next[k];
if(S1[k + 1] == Std[i])
k++;
if(k == Len1 - 1) {
Left = i - Len1 + 1;
break;
}
}
reverse(Std,Std + StdLen);
reverse(S2,S2 + Len2);
memset(Next,0,sizeof(Next));
Next[0] = k = -1;
for(int i=1;i<Len2;i++) {
while(k > -1 && S2[k + 1] != S2[i])
k = Next[k];
if(S2[k + 1] == S2[i])
k++;
Next[i] = k;
}
k = -1;
for(int i=0;i<StdLen;i++) {
while(k > -1 && Std[i] != S2[k + 1])
k = Next[k];
if(S2[k + 1] == Std[i])
k++;
if(k == Len2 - 1) {
Right = i - Len2 + 1;
break;
}
}
//cout << Left << " " << Right << endl;
if(Left == -1|| Right == -1 || Left + Len1 - 1 + Len2 + Right > StdLen) {
printf("-1");
return 0;
}
printf("%d",StdLen - (Left + Len1) - (Right + Len2) );
}
/*
abcd123ab888efghij45ef67kl,ab,ef
*/