• [USACO15FEB]Censoring S「KMP算法」


    [USACO15FEB]Censoring S「KMP算法」

    题目描述

    原题来自:USACO 2015 Feb. Silver

    给出两个字符串(S)(T),每次从前往后找到(S)的一个子串(T) 并将其删除,空缺位依次向前补齐,重复上述操作多次,直到(S)串中不含(T)串。输出最终的(S)串。

    输入格式

    第一行包含一个字符串(S),第二行包含一个字符串(T)

    输出格式

    输出处理后的(S)串。

    样例

    样例输入

    whatthemomooofun
    moo
    

    样例输出

    whatthefun
    

    思路分析

    • 如果这题是只有删除或只有查找那就很简单了,关键是这两个放在了一起……
    • 首先我们要明确一点就是删除一个(T)串后,可能会出现新的(T)串(比如样例),所以我们需要随时更新(S)串的状态
    • 因为是线性的遍历,所以模拟一个栈就可以了,栈内存储新(S)串下标,每次找到一个(T)串就将其整个弹出,维护(S)串的状态
    • 另外这里开了两个记录匹配情况的数组,分别记录,板子只开一个是因为一般情况这两个数组是等效的,所以省去了一个,但这题加上删除操作,就不等效了

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #define N 1000010
    using namespace std;
    char s[N],t[N];
    int f[N],sta[N],kmp[N],top; //kmp记录t本身的匹配情况,f记录s与t的匹配情况
    
    int main(){
    	scanf("%s%s",s+1,t+1);
    	int ls = strlen(s+1),lt = strlen(t+1);
    	for(int i = 2,j=0;i<=lt;i++){ //KMP板子
    		while(j&&t[i]!=t[j+1])j = kmp[j];
    		if(t[i]==t[j+1])j++;
    		kmp[i] = j;
    	}
    	for(int i =1,j=0;i <= ls;i++){
    		while(j&&s[i]!=t[j+1])j = kmp[j];
    		if(s[i]==t[j+1])j++;
    		f[i] = j; //与上面操作相同,记录匹配情况
    		sta[++top] = i; //入栈
    		if(j==lt){
    			top-=lt; //整个T串弹出
    			j = f[sta[top]]; //sta存的是处理后的S串的下标
    		}
    	}
    	for(int i = 1;i <= top;i++){
    		printf("%c",s[sta[i]]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    cisco/CCNA思科静态路由配置(附PKA文件)
    Web前端常用词汇大全
    解决Linux无法安装pygame问题
    CC2530常用的控制寄存器
    解决MySQL外键约束中的引用列和引用列不兼容问题
    详解使用Hyper-V安装Ubuntu Server 16.10
    虚拟机VMware下CentOS6.6安装教程图文详解
    word论文排版技法之五——标题样式关联多级列表
    如何写《软件需求规格说明书》
    VisualStudio官网使用教程
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/13344065.html
Copyright © 2020-2023  润新知