hiho 218 Keywords Filter

目录

hiho 218 Keywords Filter

题目1 : Keywords Filter

描述

输入

输出

题意分析:

1.题是什么?

2.思路

(1)ac自动机?单纯kmp?

(2)单纯kmp时间空间复杂度分析

(3)解法以及关键优化

(4)ac自动机做法

ac代码

1.单纯kmp

2.ac自动机(待补充)

hiho 218 Keywords Filter

题目1 : Keywords Filter

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

You are given a string S which consists of only lower case letters and N keyword W1, W2, … WN which also consists of only lower case letters. For each appearance of a keyword in S you need to change the letters matching the keyword into ‘*’.

Assume S = “abcxyzabcd” and keywords are {“abc”, “cd”}, the filtered S’ will be “***xyz****”.

输入

The first line contains an integer N. (1 <= N <= 1000)

The following N lines each contains a keyword. The total length of the keywords is no more than 100000.

The last line contains the string S. The length of S is no more than 100000.

输出

The filtered string.

样例输入

2  
abc  
cd  
abcxyzabcd

样例输出

***xyz****

题意分析:

1.题是什么?

    给你1000个长度为100000以内的屏蔽词,然后给你一段长度100000以内的文章,要把文章中所有屏蔽词都换成’*’号然后输出.

2.思路

(1)ac自动机?单纯kmp?

   字符串多模匹配,妥妥的ac自动机模版题的感觉啊,不过我个人有点没搞懂ac自动机的fail指针那个地方而且很久没写ac自动机了,故而ac自动机的解法后面会补上,下面放我只用kmp配合一些优化成功ac的解法:

    首先不知道kmp是什么算法的可以看我另一篇博客 kmp详解

(2)单纯kmp时间空间复杂度分析

    首先分析解法的时间复杂度,我们知道kmp时间复杂度是m+n的,故而如果单纯的用kmp,预计时间复杂度会是在1000*(100000+100000),也就是2亿,时间上勉强能接受,空间复杂度上需要先存下那1000个关键字,最极限需要1亿个char空间,空间上很悬然而我这样存没出事,看来输入是手下留情了的.

(3)解法以及关键优化

    解法是以对每个屏蔽词以kmp做匹配,匹配成功则屏蔽相应段,然而单纯这么做只能过90%数据,因为这么做存在时间复杂度暴涨的特例:

   对于文章aaaaaaaaaaaaaaaaaaaaaa,屏蔽词aaaaaa在文章中做kmp会多次匹配成功,每次都傻傻的屏蔽相应段会造成时间复杂度暴涨为(m-n)*n,几乎是m*n,故而我们需要做一下优化:

   导致时间复杂度暴涨的关键是我们重复屏蔽了某些段,故而我们只要做一个lastpingbi存最后屏蔽的地方,循环时以lastpingbi为辅助边界,就可以避免重复屏蔽,成功ac

(4)ac自动机做法

待补充

ac代码

1.单纯kmp

#include <iostream>
using namespace std;

const int maxn=100005;
string keyword[1000];

int ntext[maxn];//ntext数组 
void getntext(string s){//构造ntext数组,真正的模版
	ntext[0]=-1;
	int i=0,j=-1; //j为什么初值赋值-1?0其实也行,仅仅是为了少一个判断, 
	while(s[i]){
		if(j==-1||s[i]==s[j]) ntext[++i]=++j; 
		else j=ntext[j];
	}
}

int lastpingbi; //这个非常重要,没有这个只能过90%数据
string wordsfilter(string a,string b,string ans){
	lastpingbi=0;
	int blen=0;
	while(b[blen]) blen++;
	getntext(b);
	int i=0,j=0;
	while(a[i]){
		if(j==-1||a[i]==b[j]){
			i++,j++;
			if(!b[j]){
				for(int l=i-1;l>=std::max(lastpingbi,i-blen);l--) ans[l]='*';
				lastpingbi=i-1;
				j=ntext[j];  
			}
		}
		else j=ntext[j];  
	}
	return ans;
}


void solve(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>keyword[i]; 
	string str,ans;
	cin>>str;
	ans=str;
	for(int i=0;i<n;i++) ans=wordsfilter(str,keyword[i],ans);
	cout<<ans<<endl;
}

int main(){
	solve();
	return 0;
}

2.ac自动机(待补充)

点赞