题目大意:
有一个S串和一个T串,长度均小于1000000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程.
输出最后的U串.
那么这道题的思路就是用一个栈来维护.
关键是kmp中自我匹配的部分这里有用.
先对T串自我匹配出一个next数组:
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; } }
然后可以开始进行算法了.
算法大概建立一个栈,用来储存字符串.
若已经完全匹配了,就弹出匹配的元素,并且要将j更新为当前栈顶元素匹配到的T串的位置.
否则继续.
若相等,将指标j++.
若不相等,将指标j往前偏移,就是j=next[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); }
所以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; }感觉跟kmp模板好像啊.