列表

详情


NC50355. Censoring

描述

有一个长度不超过的字符串S。FarmerJohn希望在S中删掉n个屏蔽词(一个屏蔽词可能出现多次),这些词记为
FJ在S中从头开始寻找屏蔽词,一旦找到一个屏蔽词,FJ就删除它,然后又从头开始寻找(而不是接着往下找)。FJ会重复这一过程,直到S中没有屏蔽词为止。注意删除一个单词后可能会导致S中出现另一个屏蔽词。这n个屏蔽词不会出现一个单词是另一个单词子串的情况,这意味着每个屏蔽词在S中出现的开始位置是互不相同的,请帮助FJ完成这些操作并输出最后的S。

输入描述

第一行包含一个字符串S;
第二行包含一个整数n;
接下来的n行,每行包含一个字符串,第i行的字符串是t_i

输出描述

一行,输出操作后的S。保证S不会变成空串。

示例1

输入:

begintheescapexecutionatthebreakofdawn
2
escape
execution

输出:

beginthatthebreakofdawn

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 39ms, 内存消耗: 14968K, 提交时间: 2019-12-12 12:19:11

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1e5;

struct Node {
  int ch[26];
  int fail;
  int last;
  int val;
};
Node nodes[MAXN];
int sz;
int N;
string words[MAXN];


void insert(string s, int idx) {
  int cur = 0;
  for (auto ch: s) {
    int &nxt = nodes[cur].ch[ch-'a'];
    if (nxt == 0) nxt = ++sz;;
    cur = nxt;
  }
  nodes[cur].val = idx;
}

void build() {
  queue<int> Q; Q.push(0);
  while (!Q.empty()) {
    auto s = Q.front(); Q.pop();
    for (int i = 0; i < 26; i++) {
      int &t = nodes[s].ch[i];
      int f = nodes[s].fail;
      if (t == 0) t = nodes[f].ch[i];
      else {
        while (f && !nodes[f].ch[i]) f = nodes[f].fail;
        nodes[t].fail = !s?0: nodes[f].ch[i];
        nodes[t].last = nodes[t].val?nodes[t].val:nodes[nodes[t].fail].last;
        Q.push(t);
      }
    }
  }
}
int main() {
  string S; cin >> S;
  cin >> N;
  for (int i = 1; i <= N; i++) cin >> words[i];
  for (int i = 1; i <= N; i++) insert(words[i], i);
  build();
  string T;
  stack<int> st;
  st.push(0);
  int cur = 0;
  for (auto ch: S) {
    int id = ch - 'a';
    cur = nodes[cur].ch[id];
    T.push_back(ch);
    st.push(cur);
    // cout << ch << " " << cur << " " << nodes[cur].last << endl;
    if (nodes[cur].last) {
      int k = nodes[cur].last;
      // cout << words[k] << endl;
      for (int j = 0; j < words[k].size(); j++) T.pop_back(), st.pop();
      cur = st.top();
    }
  }
  cout << T << endl;
}

C++(clang++ 11.0.1) 解法, 执行用时: 21ms, 内存消耗: 12536K, 提交时间: 2023-02-24 18:03:59

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int SZ = 1e6+10;
char str[N], s[N];
int n, fail[SZ];
int trie[SZ][30],tot = 1,End[SZ];
void Insert(const char* s){
	int len = strlen(s), p = 1;
	for(int i = 0;i < len;i++){
		int ch = s[i]-'a';
		if(!trie[p][ch]) trie[p][ch] = ++tot;
		p = trie[p][ch];
	}
	End[p] = len;
}
queue<int> q;
void getFail(){
	for(int i = 0;i < 26;i++) trie[0][i] = 1;
	q.push(1); fail[1] = 0;
	while(!q.empty()){
		int p = q.front(); q.pop();
		for(int i = 0;i < 26;i++){
			if(!trie[p][i]) trie[p][i] = trie[fail[p]][i];
			else{
				q.push(trie[p][i]); 
				fail[trie[p][i]] = trie[fail[p]][i];
			}
		}
	}
}
char path[N];
int top = 0,Stack[N];
void solve(){
	getFail();	//为什么非要更新Fail数组呢 
	int len = strlen(str);
	for(int i = 0,p = 1;i < len;i++){
		int ch = str[i]-'a';
		p = trie[p][ch];
		Stack[++top] = p; path[top] = str[i];
		if(End[p]) top -= End[p], p = Stack[top];
	}	
	for(int i = 1;i <= top;i++) putchar(path[i]);
}
int main(){
	scanf("%s",str);
	scanf("%d",&n);
	for(int i = 1;i <= n;i++){
		scanf("%s",s); Insert(s);
	}
	solve();
	return 0;
}

上一题