【KMP】BZOJ3942-[Usaco2015 Feb] Censoring

【题目大意】

有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程。输出最后的S串。

【思路】
三天前写过一次,用的是以前的KMP模板,但是觉得太乱了,数组下标一会儿是下标一会儿是长度,傻傻分不清。参照其他人常见的方法重改了一发,算是比较清晰的KMP了,所有数组下标均直接指代字符串下标。

维护两个同进同出的栈,s代表当前的U串,a代表在s串种相应位置时的j指针位于模式串中的下标。每次将匹配串的下一位压入s中,用KMP判断匹配。一旦成功匹配到一个,便从栈中弹出即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=1000000+50;
 7 char p[MAXN],t[MAXN],s[MAXN];
 8 int next[MAXN],a[MAXN],len,lenp;
 9 
10 void getnext()
11 {
12     int i=0,j=-1;
13     next[i]=j;
14     for (int i=1;i<len;i++)
15     {
16         while (j!=-1 && p[i]!=p[j+1]) j=next[j];
17         if (p[i]==p[j+1]) ++j;
18         next[i]=j;
19     }
20 }
21 
22 void solve()
23 {
24     int top=0;
25     for (int i=0;i<len;i++)
26     {
27         int j=a[top];
28         s[++top]=t[i];
29         while (j!=-1 && p[j+1]!=s[top]) j=next[j];
30         if (p[j+1]==s[top]) ++j;
31         a[top]=j;
32         if (a[top]==lenp-1) top-=lenp;
33     }
34     s[top+1]='\0';
35     puts(s+1);
36 }
37 
38 int main()
39 {
40     scanf("%s%s",t,p);
41     len=strlen(t),lenp=strlen(p);
42     getnext();
43     solve();
44     return 0;
45 }

 

posted @ 2016-07-27 11:04  iiyiyi  阅读(790)  评论(1编辑  收藏  举报