题意:
总字符数均
<
=
1
e
6
<=1e6
<=1e6的两篇文章
S
,
T
S,T
S,T,其中把
T
T
T的每个单词换成另一个单词并且两个不同的单词不能换成同一个单词后(可以不变),与
S
S
S中的一段匹配,求最早的可能匹配的位置。
题解:
对于单词建
t
r
i
e
trie
trie树之后就可以把一个单词离散成一个编号。为啥不哈希啊不卡内存还好写。
然后使用本质匹配KMP,即每个点的值为前面第一个和它单词相同的位置与当前位置的距离,然后就完了。
#include<bits/stdc++.h>
#define LL long long
#define maxn 1000006
using namespace std;
int n=1,m=1;
char S[maxn];
int s[maxn],t[maxn],nxt[maxn],pr[maxn];
int tr[maxn][26],tot;
int main(){
for(;scanf("%s",S) && S[0]!='$';){
int p = 0 , len = strlen(S);
for(int i=0,v;i<len;i++){
if(!tr[p][v = S[i]-'0']) tr[p][v] = ++tot;
p = tr[p][v];
}
s[n] = n - pr[p] , pr[p] = n;
n++;
}
memset(pr,0,sizeof pr);
for(;scanf("%s",S) && S[0]!='$';){
int p = 0 , len = strlen(S);
for(int i=0,v;i<len;i++){
if(!tr[p][v = S[i]-'0']) tr[p][v] = ++tot;
p = tr[p][v];
}
t[m] = m - pr[p] , pr[p] = m;
m++;
}
for(int j=0,k=1;k<m;)
if(j == 0 || (min(t[j],j) == min(t[k],j))) nxt[++k] = ++j;
else j = nxt[j];
for(int i=1,j=1;i<n;i++,j++){
if(j == m){
printf("%d\n",i-m+1);
return 0;
}
while(j!=0 && min(t[j],j) != min(s[i],j)) j=nxt[j];
}
}