题目:BZOJ3942.
题目大意:有一个
S
S
S串和一个
T
T
T串,设当前串为
U
U
U串,然后从前往后枚举
S
S
S串一个字符一个字符往
U
U
U串里添加,若
U
U
U串后缀为
T
T
T,则去掉这个后缀继续流程,并输出最后的
U
U
U串.
1
≤
∣
S
∣
,
∣
T
∣
≤
1
0
6
1\leq |S|,|T|\leq 10^6
1≤∣S∣,∣T∣≤106.
我们考虑顺着题目的意思一个一个字符往 U U U串里加,同时维护当前 U U U串每一个点已经被匹配了几个字符.当当前的点已经被 T T T匹配上时,考虑去掉这个后缀 T T T(可以用栈维护),发现这样并不影响前面匹配的值,所以去掉后继续填入字符就好.
所以AC代码如下:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
const int N=1000000;
char S[N+1]={0},T[N+1]={0};
int n,m,next[N+1]={0},top=-1;
struct stack{
int now;
int c;
}s[N+1];
inline void into(){
scanf("%s",&S);
scanf("%s",&T);
n=strlen(S);
m=strlen(T);
}
inline void myself(){
int j=-1;
next[0]=-1;
for (int i=1;i<m;i++){
while (j>-1&&T[i]!=T[j+1]) j=next[j];
if (T[i]==T[j+1])j++;
next[i]=j;
}
}
inline void work(){
myself();
int j=-1;
for (int i=0;i<n;i++){
s[++top].c=S[i];
while (j>-1&&S[i]!=T[j+1]) j=next[j];
if (S[i]==T[j+1])j++;
s[top].now=j;
if (j==m-1) top-=m,j=s[top].now;
}
}
inline void outo(){
for (int i=0;i<=top;i++)
putchar(s[i].c);
}
int main(){
into();
work();
outo();
return 0;
}