题目链接:http://acm.scu.edu.cn/soj/problem.action?id=4438
给出s1、s2,要你删除s2中出现的第一个s1,并将剩下的合并成一个新的串,再继续找,直到找不到s1,输出最后的串。
///主要想记录一下模拟栈的使用(比赛的时候都没有想到它T_T,后面想用kmp里面的next数组优化下我的假算法,又不会写T_T)
kmp+模拟栈
KMP算法中,我们在主串中找模拟串,找到后就从起始点的下一位又开始匹配,找下一个模拟串出现的位置。但这里去掉s1后,它的前后有可能合并成一个新的s1串。这里我们可以用一个模拟栈,从前往后处理,在模拟栈中去匹配s1,我们用cou表模拟栈的长度,当出现s1,就执行操作:cou-=strlen(s1),直接O(1)“删掉”出现的s1,然后再往模拟栈中放入后面的字符。需要注意的是cou-=strlen(s1)后,j应该回溯到哪里(需要用一个数组来记录模拟栈每个位置前可以匹配到 s1前缀的长度)
代码:
//pos[cou]表示,模拟栈中,cou为前可以匹配到多少个字符
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
//#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define mid ((l + r)>>1)
#define chl root<<1
#define chr root<<1|1
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int manx=5e6+10;
char p[manx],str[manx],s[manx];
int net[manx],pos[manx];
int ls,lp;
void getnext()
{
net[0]=-1;
int k=-1,j=0;
while(j<lp)
{
if(k==-1||p[k]==p[j])
net[++j]=++k;
else
k=net[k];
}
}
int ans_len()
{
int cou=0,i=0,j=0;
pos[0]=0;
while(i<ls)
{
str[cou]=s[i++];
while(j!=-1&&p[j]!=str[cou])
j=net[j];
cou++,j++;
pos[cou]=j;
if(j==lp)//if这部分就是kmp中改动的部分
{
cou-=lp;
j=pos[cou];
}
}
return cou;
}
int main()
{
while(scanf("%s%s",p,s)!=EOF)
{
lp=strlen(p);
ls=strlen(s);
getnext();
str[ans_len()]='\0';
printf("%s\n",str);
}
return 0;
}
字符串哈希+模拟栈
每次判断模拟栈中倒数Len个字符的哈希值和s1是否相等
///真的每次写哈希都会错,不是哪里没有取模,就是哪里写错了wawadaku
代码:
//hhash[cou]表示前min(cou+1,len)个字符串的哈希值
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
//#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define mid ((l + r)>>1)
#define chl root<<1
#define chr root<<1|1
using namespace std;
//typedef unsigned long long LL;
typedef long long LL;
const LL manx=5e6+10;
const LL mmm=1e7+19;
const LL mod=1e9+7;
char p[manx],s[manx],ans[manx];
LL lp,ls,ttrue,mul[manx],hhash[manx];
int main()
{
mul[0]=1;
for(int i=1;i<=5e6;i++)
mul[i]=(mul[i-1]*mmm)%mod;
while(scanf("%s%s",p,s)!=EOF)
{
ttrue=0;
lp=strlen(p);
ls=strlen(s);
for(int i=0;i<lp;i++)
ttrue=(ttrue*mmm+p[i])%mod;
int cou=0,i=0;
while(i<ls)
{
ans[cou]=s[i++];
if(cou==0)
hhash[cou]=ans[0];
else if(cou>=lp)
hhash[cou]=((hhash[cou-1]-ans[cou-lp]*mul[lp-1]%mod+mod)*mmm%mod+ans[cou])%mod;
else
hhash[cou]=(hhash[cou-1]*mmm+ans[cou])%mod;
if(hhash[cou]==ttrue)
cou-=lp;
cou++;
}
ans[cou]='\0';
printf("%s\n",ans);
}
return 0;
}